--这样就可以了./* 单据记账的存储过程*/
if exists (select name from sysobjects where name = 'BillAccount_p' and type = 'p')
drop procedure BillAccount_p
go
CREATE PROC BillAccount_p
@MatPriceKind smallint, --核算方式(1,2)(按仓库核算,按存货核算)
@ReCaculate bit,--是否重新计算单价
@IOB_NO varchar(20), --根据仓库和单据类型取得单据的单号
@AccountMan varchar(20), --记账人
@AccountDate datetime --记账日期 
as
declare @UnitPrice numeric(18,5) --出入库单中的单价,为空单据不能记账
declare @iobkind varchar(20) --出入库单据类型(12种类型)
declare @sqlAccount nvarchar(2000) --记账的语句
declare @ValueType varchar(20)--记价类型(分5种:先进先出,后进先出,移动平均法,全月平均法,个别计价法)
declare @matid varchar(20) --物料代号
declare @outing numeric(18,5) --出库数量
declare @outprice numeric(18,5) --核算出的单价
declare @autoid integer --子表记录内码
declare @interrorcode integer
declare ValidBill_c Cursor local for 
select unitprice from iobill_det_tb where iob_no = @iob_no --用于有空单价的单据的处理,不记账,返回前台作提示处理
open ValidBill_c
Fetch next from ValidBill_c into @UnitPrice
while @@Fetch_Status = 0 
begin
if @UnitPrice is null
return 9999
fetch next from ValidBill_c into @UnitPrice
end 
close ValidBill_c
deallocate ValidBill_c
select @iobkind=iob_kind_id from iobill_hed_tb where iob_no = @iob_no
set @sqlAccount = N'Insert into InventoryDetail_TB (IOB_NO, IOB_Kind_ID, IOB_Date, IOB_WH_ID, 
IOB_WHer,iob_adversary,io_flag,makedate,maker,Accounter, AccountDate,
hedmemo, iodetid,mat_id,batchno,producedate,voiddate,correspondingno,correspondingid,detmemo,
iob_adv_dep,CustID,ProvdID,in_num,in_price, in_money,out_num,out_price,out_money)
select a.iob_no,iob_kind_id,iob_date,iob_wh_id,iob_wher,iob_adversary,io_flag,makedate,maker,
accounter, accountdate, a.memois, 
b.autoid,mat_id,batchno,producedate,voiddate,b.correspondingno,b.correspondingid,b.memois,'
if @iobkind = 'MaterialsIn' 
set @sqlAccount = @sqlAccount + N'iob_adv_dep,null,null,io_num,unitprice,moneyis,null,null,null '
else if @iobkind = 'MaterialsOut' 
set @sqlAccount = @sqlAccount + N'iob_adv_dep,null,null,null,null,null, io_num,unitprice,moneyis '
else if @iobkind = 'SaleIn' 
set @sqlAccount = @sqlAccount + N'null,iob_adv_dep,null,io_num,unitprice,moneyis,null,null,null '
else if @iobkind = 'SaleOut' 
set @sqlAccount = @sqlAccount + N'null,iob_adv_dep,null,null,null,null, io_num,unitprice,moneyis '
else if @iobkind = 'StockIn' 
set @sqlAccount = @sqlAccount + N'null,null,iob_adv_dep,io_num,unitprice,moneyis,null,null,null '
else if @iobkind = 'StockOut' 
set @sqlAccount = @sqlAccount + N'null,null,iob_adv_dep,null,null,null, io_num,unitprice,moneyis '
else if PATINDEX('%in%',@iobkind) > 0 
set @sqlAccount = @sqlAccount + N'iob_adv_dep,null,null,io_num,unitprice,moneyis,null,null,null '
else 
set @sqlAccount = @sqlAccount + N'iob_adv_dep,null,null,null,null,null, io_num,unitprice,moneyis 'set @sqlAccount = @sqlAccount + N'from iobill_hed_tb a
join iobill_det_tb b on a.iob_no = b.iob_no where a.iob_no = ''' + @iob_no + ''''if @ReCaculate = 1
begin
begin tran
if @MatPriceKind = 1 --按仓库核算
begin
select @ValueType = WhValueStyle from WareHouseList_TB a join iobill_hed_tb b on 
a.WH_ID = b.iob_wh_id where b.iob_no = @iob_no
if right(@iobkind,3) = 'out' 
begin
declare DetailBill_c cursor local for
select mat_id,io_num, a.autoid from iobill_det_tb a join iobill_hed_tb b
on a.iob_no = b.iob_no where a.iob_no = @iob_no 
open DetailBill_c
fetch next from DetailBill_c into @matid, @outing, @autoid
while @@fetch_status = 0
begin
if @ValueType = '先进先出' or @ValueType = '先进先出法' 
exec FIFO_Out_Price_p @matid, @outing, 'O', 1, @outprice output
else if @ValueType = '后进先出' or @ValueType = '后进先出法'
exec FIFO_Out_Price_p @matid, @outing, 'O', 0, @outprice output
else if @ValueType = '个别计价法'
exec ZhiDing_Price_p @matid, @outprice output
else if @ValueType = '移动平均法'
exec AveMove_Price_p @matid, 1, @outprice output 
-- else if @ValueType = '全月平均法'
-- exec AveMove_Price_p @matid, 0, @outprice output 
select @interrorcode = @@error
if @interrorcode = 0
begin
update iobill_det_tb set unitprice = @outprice, moneyis = io_num * @outprice,
okprice = @outprice, okmoney = io_num * @outprice where autoid = @autoid
select @interrorcode = @@error
if @interrorcode = 0
begin
update iobill_hed_tb set accounter = @Accountman, accountdate = @AccountDate where iob_no = @iob_no
select @interrorcode = @@error
if @interrorcode <> 0 goto err
end 
else goto err
end
else goto err
fetch next from DetailBill_c into @matid, @outing, @autoid
end
close DetailBill_c
Deallocate DetailBill_c 
end
else --如果是入库的就只更新出入库主表的记账标志
begin
update iobill_hed_tb set accounter = @Accountman, accountdate = @AccountDate where iob_no = @iob_no  
if @@error <> 0 goto err
end
end
else if @MatPriceKind = 2 --按存货核算
begin
declare DetailRec_c cursor local for
select mat_id,io_num,a.autoid from iobill_det_tb a join iobill_hed_tb b
on a.iob_no = b.iob_no where a.iob_no = @iob_no
open DetailRec_c
fetch next from DetailRec_c into @matid, @outing, @autoid
while @@fetch_status = 0 
begin
select @ValueType = ValueStyle from material_all_tb a join iobill_det_tb b on 
a.mat_id = b.mat_id where b.iob_no = @iob_no and a.mat_id = @matid
if @ValueType = '先进先出'
begin
begin tran tran2
if @ValueType = '先进先出'  
exec FIFO_Out_Price_p @matid, @outing, 'O', 1, @outprice output
else if @ValueType = '后进先出'
exec FIFO_Out_Price_p @matid, @outing, 'O', 0, @outprice output
else if @ValueType = '个别计价法'
exec ZhiDing_Price_p @matid, @outprice output
else if @ValueType = '移动平均法'
exec AveMove_Price_p @matid, 1, @outprice output 
-- else if @ValueType = '全月平均法'
-- exec AveMove_Price_p @matid, 0, @outprice output 
select @interrorcode = @@error
if @interrorcode = 0
begin
update iobill_det_tb set unitprice = @outprice, moneyis = io_num * @outprice,
okprice = @outprice, okmoney = io_num * @outprice where autoid = @autoid
if @@error <> 0 goto err
update iobill_hed_tb set accounter = @Accountman, accountdate = @AccountDate where iob_no = @iob_no
if @@error <> 0 goto err
end
else goto err
end
fetch next from DetailRec_c into @matid, @outing, @autoid
end
close DetailRec_c
deallocate DetailRec_c
end
end
else --不重新计算
begin
begin tran
update iobill_hed_tb set accounter = @Accountman, accountdate = @AccountDate where iob_no = @iob_no
if @@error <> 0 goto err
end
print @sqlaccount
if @interrorcode = 0
exec(@sqlAccount)
if @@error <> 0 goto err
print 'hello2'
print @interrorcode
if @@trancount > 0
commit tran
return 0err: 
if @@trancount > 0
rollback tran
return 8888GO

解决方案 »

  1.   

    close ValidBill_c 
    deallocate ValidBill_c
      

  2.   

    主要是游标的作用域问题.默认情况下,定义的游标是全局的,所以第二次调用就会有问题.
    定义成局部的就行了.declare 游标名 cursor local --local就是指定游标为局部的.
    for select ...
      

  3.   

    LOCAL指定该游标的作用域对在其中创建它的批处理、存储过程或触发器是局部的。该游标名称仅在这个作用域内有效。在批处理、存储过程、触发器或存储过程 OUTPUT 参数中,该游标可由局部游标变量引用。OUTPUT 参数用于将局部游标传递回调用批处理、存储过程或触发器,它们可在存储过程终止后给游标变量指派参数使其引用游标。除非 OUTPUT 参数将游标传递回来,否则游标将在批处理、存储过程或触发器终止时隐性释放。如果 OUTPUT 参数将游标传递回来,游标在最后引用它的变量释放或离开作用域时释放。GLOBAL指定该游标的作用域对连接是全局的。在由连接执行的任何存储过程或批处理中,都可以引用该游标名称。该游标仅在脱接时隐性释放。
      

  4.   

    游标的作用域问题,改为cursor local