sql游標


在數據庫中的數據查詢過程中,有時候需要用到游標。

考慮到游標在查詢過程中是面向逐行的思維和我們查詢的思維是面向集合的思維產生了歧義。

同樣的,在性能上,游標會吃更多的內存,減少可用的並發,占用寬帶,鎖定資源。

在有些地方不能避開使用游標的地方,我采用了臨時表的方式,來代替游標,這樣也避免了游標每次打開關閉釋放占用的資源。

1.這是我用雙重游標的語句:

begin tran 
declare @cus varchar(20)
set @cus=:cus
declare @cus1 varchar(20)
set @cus1=:cus1
declare @sdd datetime
declare @edd datetime
set @sdd=:sd
set @edd=:ed
declare @wh_yl varchar(20)
create table mc_tmp_tb
(ml_no varchar(50),tz_no varchar(50),prd_no varchar(50),est_itm integer,co integer,
wh varchar(50),qty float,qty_over float,qty_lc float,cus_no varchar(20)
)
/*廠商遍歷*/
DECLARE cucus cursor for 
select cus_no from cust where cus_no>=@cus and cus_no<=@cus1
open cucus 
declare @cusneed varchar(20)
fetch next from cucus into @cusneed
while @@fetch_status=0
begin
select @wh_yl=wh from my_wh where cus_no=@cusneed
declare mycu cursor for
select tf_ml.ml_no,tf_ml.tz_no ,tf_ml.prd_no ,tf_ml.est_itm ,count(*) as co from tf_ml 
left join mf_ml on tf_ml.ml_no=mf_ml.ml_no
where 
mf_ml.cus_no=@cusneed
and mf_ml.ml_dd>=@sdd
and mf_ml.ml_dd<=@edd
AND tf_ml.mlid='M4'
--測試+領料單號
group by tf_ml.ml_no,tf_ml.tz_no ,prd_no ,est_itm
declare @ml_no varchar(50)
declare @tz_no varchar(50)
declare @prd_no varchar(50)
declare @est_itm integer
/*游標保存數據*/
declare @co integer
declare @wh varchar(20)
declare @qty float
declare @qty_over float
declare @qty_lc float
declare @cus_tb varchar(20)
open mycu
fetch next from mycu into @ml_no,@tz_no,@prd_no,@est_itm,@co
/*查詢出倉庫*/
while @@fetch_status=0
begin
/*查詢倉庫*/
/*單獨領余料倉或者沒有領余料倉的料*/
if(@co=1)
begin
select @wh=wh,@qty=tf_ml.qty,@qty_over=qty_over,@qty_lc=qty_lc,@cus_tb=cus_no 
from tf_ml left join mf_ml on tf_ml.ml_no=mf_ml.ml_no
AND tf_ml.mlid<>'M5' 
where tf_ml.ml_no=@ml_no and tf_ml.tz_no=@tz_no and prd_no=@prd_no and est_itm=@est_itm
end
/*領了余料倉的料*/
if(@co=2)
begin
select @wh=wh,@qty=tf_ml.qty,@qty_over=qty_over,@qty_lc=qty_lc,@cus_tb=cus_no 
from tf_ml left join mf_ml on tf_ml.ml_no=mf_ml.ml_no 
where tf_ml.ml_no=@ml_no and tf_ml.tz_no=@tz_no and prd_no=@prd_no and est_itm=@est_itm and wh<>@wh_yl
and tf_ml.mlid<>'M5' 
end
/*插入數據表*/
insert into mc_tmp_tb values (@ml_no,@tz_no,@prd_no,@est_itm,@co,@wh,@qty,@qty_over,@qty_lc,@cus_tb)
fetch next from mycu into @ml_no,@tz_no,@prd_no,@est_itm,@co
end
close mycu
deallocate mycu
--select * from mc_tmp_tb
fetch next from cucus into @cusneed
end
close cucus
deallocate cucus
select a.cus_no,a.ml_no,a.prd_no,a.wh,sum(a.qty) as 本地倉領出量 ,sum(a.qty_over) as 超發量,sum(a.qty_lc) as 余料倉使用量,case when a.wh=@wh_yl then sum(qty_lc) else sum(a.qty+a.qty_lc) end as 本次領出量小計,sum(a.qty+a.qty_over) as 本地倉出庫量小計 ,sum(b.qty_rsv) as 托工需求量小計
from mc_tmp_tb a
left join tf_tw b on a.tz_no=b.tw_no and a.prd_no=b.prd_no and a.est_itm=b.itm

group by a.ml_no,a.prd_no,a.wh,a.cus_no
order by a.cus_no,a.ml_no,a.wh 
drop table mc_tmp_tb
if @@error=0
begin
commit
end
else
begin
rollback
end

 

2.這是我去掉游標,使用臨時表的方式:

begin tran                             
declare @cus varchar(20)
set @cus=:cus
declare @cus1 varchar(20)
set @cus1=:cus1
declare @sdd datetime
declare @edd datetime
set @sdd=:sd
set @edd=:ed
declare @wh_yl varchar(20)
--查詢臨時表保存數據
declare @ml_no varchar(50)
declare @tz_no varchar(50)
declare @prd_no varchar(50)
declare @est_itm integer
declare @co integer
--保存查詢出的數據,用於插入數據
declare @wh varchar(20)
declare @qty float
declare @qty_over float
declare @qty_lc float
declare @cus_tb varchar(20)
declare @rowid1 int
create table #t_mc_tmp_tb
(ml_no varchar(50),tz_no varchar(50),prd_no varchar(50),est_itm integer,co integer,
wh varchar(50),qty float,qty_over float,qty_lc float,cus_no varchar(20)
)
/*廠商遍歷*/
declare @cusneed varchar(20)
select rowid=identity(int,1,1),flag=0,cus_no into #tmp_cus from cust where cus_no>=@cus and cus_no<=@cus1 and cus_no in (select cus_no from mf_ml where ml_dd>=@sdd and ml_dd<=@edd and mlid='M4')
declare @rowid int
select @rowid=min(rowid) from #tmp_cus where flag=0
while @rowid is not null
BEGIN
    select @cusneed=cus_no from #tmp_cus where rowid=@rowid
    --余料倉
    select @wh_yl=wh from my_wh where cus_no=@cusneed
    --保存領料信息
    --變臨時表循環
    select rowid1=identity(int,1,1),flag1=0, tf_ml.ml_no,tf_ml.tz_no ,tf_ml.prd_no ,tf_ml.est_itm ,count(*) as co into #tmp_dat from tf_ml                               
            left join mf_ml on tf_ml.ml_no=mf_ml.ml_no
            where mf_ml.cus_no=@cusneed and mf_ml.ml_dd>=@sdd and mf_ml.ml_dd<=@edd AND tf_ml.mlid='M4' group by tf_ml.ml_no,tf_ml.tz_no ,prd_no ,est_itm
    
    select @rowid1=min(rowid1) from #tmp_dat where flag1=0
    --內部循環
    while @rowid1 is not null 
    begin
        --對應行的數據查詢保存
        select @ml_no=ml_no,@tz_no=tz_no,@prd_no=prd_no,@est_itm=est_itm,@co=co from #tmp_dat where rowid1=@rowid1
        /*單獨領余料倉或者沒有領余料倉的料*/
        if(@co=1)
        begin
            select @wh=wh,@qty=tf_ml.qty,@qty_over=qty_over,@qty_lc=qty_lc,@cus_tb=cus_no 
                from tf_ml left join mf_ml on tf_ml.ml_no=mf_ml.ml_no                                                
                where tf_ml.ml_no=@ml_no and tf_ml.tz_no=@tz_no and prd_no=@prd_no and est_itm=@est_itm
                AND tf_ml.mlid<>'M5'   
        end
        /*領了余料倉的料*/
        if(@co=2)
        begin
            select @wh=wh,@qty=tf_ml.qty,@qty_over=qty_over,@qty_lc=qty_lc,@cus_tb=cus_no 
                from tf_ml left join mf_ml on tf_ml.ml_no=mf_ml.ml_no  
                where tf_ml.ml_no=@ml_no and tf_ml.tz_no=@tz_no and prd_no=@prd_no and est_itm=@est_itm and wh<>@wh_yl
                and tf_ml.mlid<>'M5'                                                  
        end
        /*插入數據表*/
        insert into #t_mc_tmp_tb values (@ml_no,@tz_no,@prd_no,@est_itm,@co,@wh,@qty,@qty_over,@qty_lc,@cus_tb)
        update #tmp_dat set flag1=1 where rowid1=@rowid1
        select @rowid1=min(rowid1) from #tmp_dat where flag1=0
    end
    --內部循環結束
    update #tmp_cus set flag=1 where rowid=@rowid
    select @rowid=min(rowid) from #tmp_cus where flag=0
    drop table #tmp_dat
end
select  a.cus_no,
a.ml_no,
a.prd_no,
a.wh,sum(a.qty) as 本地倉領出量 ,
sum(a.qty_over) as 超發量,sum(a.qty_lc) as 余料倉使用量,
case when a.wh=@wh_yl then sum(qty_lc) else  sum(a.qty+a.qty_lc) end as 本次領出量小計,
sum(a.qty+a.qty_over) as 本地倉出庫量小計 ,
sum(b.qty_rsv) as 托工需求量小計
    --collate Compatibility_198_804_30001
    from #t_mc_tmp_tb a
    left join tf_tw b on a.tz_no COLLATE Compatibility_198_804_30001 =b.tw_no 
    and a.prd_no COLLATE Compatibility_198_804_30001 =b.prd_no and a.est_itm =b.itm
    group by a.ml_no,a.prd_no,a.wh,a.cus_no
    order by a.cus_no,a.ml_no,a.wh                     
drop table #t_mc_tmp_tb
drop table #tmp_cus
if @@error=0
begin
    commit
end
else
begin
    rollback
end

 

******************************************************

在游標的使用過程中使用不當會導致鎖堵塞。所以在必須使用游標的情況下,正確的使用游標。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM