首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > SQL Server >

!心急如焚!关于存储过程的有关问题,请高手们救命

2013-02-19 
十万火急!心急如焚!关于存储过程的问题,请高手们救命!问题如下面蓝色字体所述:if exists (select * from d

十万火急!心急如焚!关于存储过程的问题,请高手们救命!
问题如下面蓝色字体所述:

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[pro_Mate_Out_CheckNo]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[pro_Mate_Out_CheckNo]
GO

SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO

/*---------------------------------
  过程名称:原料出库【反审】
  修改内容:
-----------------------------------*/
CREATE PROCEDURE pro_Mate_Out_CheckNo @UserName nvarchar(50)
WITH ENCRYPTION AS
SET XACT_ABORT ON
Begin Transaction

  --00 读取参数
  Declare @ProcName nvarchar(50)
  Declare @BillCode nvarchar(50)

  Select @ProcName = 'pro_Mate_Out_CheckNo'

  Select @BillCode = FValue
  From Base_Procedure
  Where FItem = '单号'
  And FUserName = @UserName
  And FProcName = @ProcName

  Declare @Count int --计数器
  Declare @Type nvarchar(50)  --单据类型
  Declare @State nvarchar(50) --单据状态

  Select @Type = FType,
         @State = FState
  From Mate_OutHead
  Where FCode = @BillCode

  --01 检查数据的完整性和有效性

  --0101 单据状态检查
  If IsNull(@State,'') <> '审核'
  Begin
    Rollback
    RaisError('操作无效!只有审核的单据才能反审。', 11, 1)
    Return
  End

  --0102 表体物料不能为空
  Select @Count = Count(*)
  From Mate_OutBody
  Where FHead = @BillCode
  And IsNull(FMaterialCode,'') = ''

  If @Count > 0
  Begin
    Rollback
    RaisError('物料编号有为空的记录,不能反审!', 11, 1)
    Return
  End

  --0103 表体仓位不能为空
  Select @Count = Count(*)
  From Mate_OutBody
  Where FHead = @BillCode
  And IsNull(FPlaceName,'') = ''

  If @Count > 0
  Begin
    Rollback
    RaisError('仓位有为空的记录,不能反审!', 11, 1)
    Return
  End

  --02 更新库存数据

  --0201 增加物料表的数量和金额
  Update Mate_Material
  Set FAmount = IsNull(FAmount,0) + F1,
      FMoney = IsNull(FMoney,0) + F2
  From (Select FMaterialCode, Sum(IsNull(FAmount,0)) As F1, Sum(IsNull(FMoney,0)) As F2
        From Mate_OutBody
        Where FHead = @BillCode
        Group By FMaterialCode) As T1
  Where FCode = FMaterialCode

  --03 更新库存关系表


  --0301 插入库存关系表的缺少记录
  Insert Into Mate_Relation(FMaterialCode, FPlaceName)
    Select Distinct FMaterialCode, FPlaceName
    From Mate_OutBody
    Where FHead = @BillCode
    And (FMaterialCode + FPlaceName) Not In
        (Select IsNull(FMaterialCode,'') + IsNull(FPlaceName,'') From Mate_Relation)

  --0302 增加库存关系表的数量
  Update Mate_Relation
  Set FAmount = IsNull(FAmount,0) + F1
  From (Select FMaterialCode, FPlaceName, Sum(IsNull(FAmount,0)) As F1
        From Mate_OutBody
        Where FHead = @BillCode
        Group By FMaterialCode, FPlaceName) As T1
  Where Mate_Relation.FMaterialCode = T1.FMaterialCode
  And Mate_Relation.FPlaceName = T1.FPlaceName

--上面红色部分偶尔没有执行,但下面的状态更新却执行了。结果导致单据反审了,但库存数量却没有增加。
--这种现象并不常出现,单独测试这个存储过程的时候不出问题,不知道为什么?请帮我看一下,多谢!
--我用的是SQLServer2000,已打SP4补丁了。
--如果需要相应的数据库和程序,我可以打包发给你。

  --04 更新物料表
  Execute pro_Insert_Proc @UserName, 'pro_Mate_Update', '单号', ''
  Execute pro_Insert_Proc @UserName, 'pro_Mate_Update', '类型', '物料档案'
  Execute pro_Mate_Update @UserName

  --05 更新状态
  Update Mate_OutHead
  Set FState = '提交',
      FCheckName = Null,
      FCheckDate = Null
  Where FCode = @BillCode


Commit

GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
SQL?Server 存储过程 Update 事务处理
[解决办法]
放到一个事务里面来保证业务的一致性。这才是最重要的。
[解决办法]
加锁是一种方式,但是如果你的update不够快,会造成阻塞甚至死锁。你把这套逻辑处理放在
begin tran 
代码块
commit/rollback
中。
[解决办法]
中间那块没有执行我个人觉得:
1、你的@count每次用完没有重置,影响了,试试每次使用钱先set @count=0。
2、那段红字部分的条件不符合,导致执行了,但是没结果,所以你看到是没执行。
[解决办法]
对于9楼,如果你觉得比较大的可能行,那么你可以尝试加锁,但是应该有规律检查一下是否会更慢或者有死锁。
对于10楼,业务我不熟,写法上我帮不了你,但是如果觉得慢,可以把执行计划贴出来看看

刚才加班去了。现在才搞完
[解决办法]
我個人覺得這問題應該從數據上去查,語句沒什麽就是數據的問題了。
你可以做個日誌表跟蹤下更新庫存的過程.

e.g.

  --0201 增加物料表的数量和金额
  Update Mate_Material
  Set FAmount = IsNull(FAmount,0) + F1,
      FMoney = IsNull(FMoney,0) + F2
  From (Select FMaterialCode, Sum(IsNull(FAmount,0)) As F1, Sum(IsNull(FMoney,0)) As F2
        From Mate_OutBody
        Where FHead = @BillCode


        Group By FMaterialCode) As T1
  Where FCode = FMaterialCode

if @@rowcount =0  --写日志
begin
   insert into db_log ....
end

不写日志也可以,使用rollback 方法并告诉客户端,找不到对应的库存数据无法更新库存,也说明这原料在仓库有问题。


热点排行