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

游标换成循环,多谢

2013-11-06 
游标换成循环,,,谢谢declare Level1 cursor forselect companyid,dptid,dptname,capcode,oldcode,storplac

游标换成循环,,,谢谢

  declare Level1 cursor for                                                  
  select companyid,dptid,dptname,capcode,oldcode,storplace_id,storplace,deptype,years,months,buydate,usedate,chief,chiefcode,examiner,paymethod,                                                  
         rowid,Capcode,Capname,round(orivalue/qty,2)  as price, qty,round(depvalue/qty,2) as depvalue,round(salvalue/qty,2) as salvalue,orivalue,depvalue,memo,usetype,        
         usercode,username                                  
  from VfCapdocA with (nolock)                                                  
  where doccode=@doccode                                
                                  
                                  
  select @CardNo=0                      
                                                    
  open Level1       
                                             
  fetch next from Level1 into @companyid,@dptid,@dptname,@capcode,@oldcode,@storplace_id,@storplace,@deptype,@years,@months,@buydate,@docdate,@chief,@chiefcode,@examiner,                                                  
                              @paymethod,@rowid,@Capcode,@Capname,@price,@digit,@depvalue,@salvalue,@allorivalue,@alldepvalue,@memo,@usetype,@usercode,@username                                                  
  while @@fetch_status=0                                                  
  begin                                                  
     set @i=1                                                  
                          
     while @i<=@digit                                                  
     begin                                                  



        update FaCardNoA                                                  
        set CardNo=isnull(cardno,0)+1                                                  
        where Capcode=@Capcode                                            
        if @@rowcount=0                                          
        begin                                        
           insert into FaCardNoA(Capcode,CardNo) values(@Capcode,1)                                        
         end                                      
                                  
                                                 
                                     
          select @CardNo=CardNo from FaCardNoA where Capcode=@Capcode                                         
          select @cardid=@Capcode+                                                  
                 case when @CardNo>=1 and @CardNo<=9 then '000'+convert(varchar(1),@CardNo)                                                   
                      when @CardNo>=10 and @CardNo<=99 then '00'+convert(varchar(2),@CardNo)                                                  
                      when @CardNo>=100 and @CardNo<=999 then '0'+convert(varchar(3),@CardNo)                        
                      when @cardno>=1000 and @cardno<=9999 then convert(varchar(4),@cardno)                                     
                 else 'OK'                                                  


                 end                                                  
                                                  
          if right(@cardid,2)='OK'                                    
             begin                                                  
                close Level1                                                  
                deallocate Level1                                                  
                raiserror('超出编码长度!',16,1)                                      
                return                                                  
             end                                                  
                                                  
            if @i=@digit                                                  
              begin                                                  
                set @price=isnull(@allorivalue,0)-(@digit-1)*isnull(@price,0)                                                 
                set @depvalue=isnull(@alldepvalue,0)-(@digit-1)*isnull(@depvalue,0)                                                  
                                                  
              end                                                  


          
           select @oppocompanyid=isnull(oppocompanyid,''),@oppocompanyname=isnull(oppocompanyname,'')                                                 
           from fcapdocA_d where rowid=@rowid                                                  
                                                  
                                                      
                                                  
    exec getxxxx @detailrowid output                                                   
                                                  
--生成子表数据                                                  
          insert into fCapSubdocA(detailrowid,rowid,cardid,Capcode,Capname,qty,price,orivalue,depvalue,salvalue,netvalue,doccode,flag)                                                  
   values(@detailrowid,@rowid,@cardid,@Capcode,@Capname,1,@price,@price,@depvalue,@salvalue,isnull(@price,0)-isnull(@depvalue,0),@doccode,                                                  
                 case when @paymethod='估价' then 1 else 0 end)                                              
   if @@rowcount=0                                                 
      begin                                                  
        close Level1                                                  
        deallocate Level1               
            raiserror('更新数据有误!',16,1)                                                  
            return                                                  


      end                                                    
                                             
--生成卡片                                     
                                                
          insert into facardA(Cardid,oldcode,storplace_id,storplace,companyid,dptid,dptname,capcode,oppocompanyid,oppocompanyname,deptype,years,months,indate,usedate,usestatus,chief,chief_code,examiner,status,CapValue,memo,usetype,rowid,usercode,username
,cardtype)            
         values(@cardid,@oldcode,@storplace_id,@storplace,@companyid,@dptid,@dptname,@capcode,@oppocompanyid,@oppocompanyname,@deptype,@years,@months,@buydate,@docdate,'使用',@chief,@chiefcode,@examiner,case when @paymethod='估价' then 1 else 0 end,@price,@me
mo,@usetype  
,@rowid,@usercode,@username,1)  
                                        
   if @@rowcount=0                                                  
      begin                                                  
        close Level1                                                  
        deallocate Level1                                                  
        raiserror('更新数据有误!',16,1)                                                  
        return                                                  
      end                                                  
                                          
   select @i=@i+1                                                  
 end                                           
                                                  
 fetch next from Level1 into @companyid,@dptid,@dptname,@capcode,@oldcode,@storplace_id,@storplace,@deptype,@years,@months,@buydate,@docdate,@chief,@chiefcode,@examiner,                                                  


                              @paymethod,@rowid,@Capcode,@Capname,@price,@digit,@depvalue,@salvalue,@allorivalue,@alldepvalue,@memo,@usetype,@usercode,@username                                                 
    end                                                  
    close Level1                                                  
deallocate Level1  


[解决办法]
1.  VfCapdocA表与FaCardNoA表是什么关系?一对多的吗?
2.  FaCardNoA.CardNo的编码有什么规则?你那样写case语句判断那么多,应该改用Stuff()函数去处理
3.  你获取最大的@cardid,其实不用那么麻烦,自己生成的编号,算出来后还要判断?
4.  更新FaCardNoA,  插入fCapSubdocA,  再插入facardA


update FaCardNoA可以改进,生成@cardid也可以改进


[解决办法]
请问游标换成循环的目的是什么?
游标换成循环对性能提升没有意义.
应换成表关联更新的方式较好喔.
[解决办法]
--#1.用不用游标,先测试一下效率再说:
DECLARE @id INT, @doccode INT

DECLARE cursor_Level1 CURSOR STATIC LOCAL FORWARD_ONLY READ_ONLY--1.定义成这个类型的游标: STATIC LOCAL FORWARD_ONLY READ_ONLY
FOR
SELECT id--2.你游标中的变量太多了,如果可以的话,用主键查询方式代替
FROM dbo.VfCapdocA WITH (NOLOCK)
where doccode=@doccode

OPEN cursor_Level1
FETCH NEXT FROM cursor_Level1 INTO @id

WHILE (@@FETCH_STATUS = 0) 
BEGIN
--3.用空循环测试一下你游标的效率
/*
    insert into fCapSubdocA
SELECT * FROM VfCapdocA WHERE id = @id--2.你游标中的变量太多了,如果可以的话,用主键查询方式代替
*/

FETCH NEXT FROM cursor_Level1 INTO @id
END

CLOSE cursor_Level1
DEALLOCATE cursor_Level1

--#2.循环的效率,不一定比游标好.需要自己测试一下
--#3.当然了,如果不用游标,直接把所有的逻辑用查询实现,一般来说性能最好.
--总结:游标可用;循环不一定就比游标快,还是要了解一下游标和循环之间的性能差异到底在哪儿。对于楼主的需求,个人推荐可用游标(除非测试#1空循环的性能特别差)

[解决办法]
引用:
主要现在是感觉游标可能会占用较大的内存,所以现在想改成循环,,,

游标换成循环对性能提升没有意义.
[解决办法]
引用:
Quote: 引用:

Quote: 引用:

主要现在是感觉游标可能会占用较大的内存,所以现在想改成循环,,,

游标换成循环对性能提升没有意义.


这我原来写的游标,主要别人给我说用临时表的循环要比这个好一点,能给简单说下循环和游标对性能的影响吗?


其实用循环和游标,之所以对性能有影响,根本的原因在于,处理数据的方式,也就是取出1条数据,然后处理,处理完成后,再取出下一条,

如果你的表有1000w条数据,那么就得循环1000w次,效率肯定是非常低的。

同样的,如果单纯的sql语句,之所以性能相对较好的原因在于,他是以集合为单位来处理数据,也就是批处理,一次能把所有的数据都处理好。

当然,有时候,由于业务逻辑非常复杂,可能需要写多个语句,每个语句先把中间的结果插入到一个临时表中,然后最后再对临时表进行处理,这也是一个变通的办法,但尽量不要用游标或者是循环来处理数据,因为效率比较低。
[解决办法]
通常使用游标都是不得已的情况,大部分的时候可以使用迭代来解决游标或者是循环的问题。 

具体得看需求,lz这个光是代码,没有需求关系的话,很难进行适当的改写。 

热点排行