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

sql server 游标!该怎么解决

2013-12-30 
sql server 游标!本人对游标不懂,所以在这求点游标的例子(从易到难带注释),我自己来做练习.[解决办法]crea

sql server 游标!
本人对游标不懂,所以在这求点游标的例子(从易到难带注释),我自己来做练习.


[解决办法]

create table table1
(KHMC varchar(20), SPDM varchar(10), DJ varchar(10), SL int, XSSL int)

insert into table1
 select '广西骆俊峰', '5609B', '100.0000', 12, null union all
 select '广西骆俊峰', '5609B', '80.0000', 7, null union all
 select '广西骆俊峰', '5609B', '60.0000', 6, null union all
 select '广西骆俊峰', '5609B', '50.0000', 13, null union all
 select '广西骆俊峰', '5609B', '40.0000', 21, null


create table table2
(khmc varchar(20), spdm varchar(10), sl int, bysl int)

insert into table2
 select '广西骆俊峰', '5609B', 20, null
 


declare @table1_khmc varchar(10)
declare @table1_spdm varchar(20)
declare @table1_sl int
declare @table1_xssl int

--定义table1的游标
declare cur_table1 cursor
for select KHMC,SPDM,sl,xssl from table1 for update  --可以游标更新的


declare @table2_khmc varchar(10)
declare @table2_spdm varchar(20)
declare @table2_sl int


--定义table2的游标
declare cur_table2 cursor
for select khmc,spdm,sl from table2   --用于查询的游标
 

open cur_table2;  --打开游标

--从游标中取数,放到变量中
fetch next from cur_table2 into @table2_khmc,@table2_spdm,@table2_sl


while @@FETCH_STATUS = 0   --外层游标cur_table2的遍历
begin
   open cur_table1;
   fetch next from cur_table1 into @table1_khmc,@table1_spdm,@table1_sl,@table1_xssl
   
   while @@FETCH_STATUS = 0  --内存游标cur_table1的遍历
   begin
      if (@table1_khmc = @table2_khmc) and (@table2_spdm = @table1_spdm)
      begin
update table1
set xssl = case when @table2_sl >= isnull(@table1_sl,0)
                     then @table1_sl
                when @table2_sl < isnull(@table1_sl,0)
                     then @table2_sl
           end
where current of cur_table1;

--如果table2的sl大于table1的sl,那么可以继续循环,否则就退出内层有游标
if @table2_sl >= isnull(@table1_sl,0)
   set @table2_sl = @table2_sl - ISNULL(@table1_sl,0);
else
   break;
   
fetch next from cur_table1 into @table1_khmc,@table1_spdm,@table1_sl,@table1_xssl
  end
  
   end
   
   close cur_table1; --关闭内层游标
   
   fetch next from cur_table2 into @table2_khmc,@table2_spdm,@table2_sl
   
end

close cur_table2;   --关闭游标

deallocate cur_table2;  --释放游标cur_table2的资源

deallocate cur_table1;  --释放游标cur_table1的资源


--查询更新后的结果
select *
from table1
/*
KHMC    SPDMDJ      SLXSSL
广西骆俊峰5609B100.0000  1212
广西骆俊峰5609B80.0000  7    7
广西骆俊峰5609B60.0000  6    1
广西骆俊峰5609B50.0000  13NULL
广西骆俊峰5609B40.0000  21NULL
*/

[解决办法]
上面的例子稍微有点难度,是2层游标,实现了比较复杂的逻辑。

看看,这个是完整的例子:

游标
http://blog.csdn.net/sqlserverdiscovery/article/details/12657219


[解决办法]
这是一个相对简单的例子,就是输出每天记录的值:

create table table1
(KHMC varchar(20), SPDM varchar(10), DJ varchar(10), SL int, XSSL int)


 
insert into table1
 select '广西骆俊峰', '5609B', '100.0000', 12, null union all
 select '广西骆俊峰', '5609B', '80.0000', 7, null union all
 select '广西骆俊峰', '5609B', '60.0000', 6, null union all
 select '广西骆俊峰', '5609B', '50.0000', 13, null union all
 select '广西骆俊峰', '5609B', '40.0000', 21, null
 go
 
 
 
declare cur_table1 cursor
for select * from table1

declare @KHMC varchar(20)
declare @SPDM varchar(10)
declare @DJ varchar(10)
declare @SL int
declare  @XSSL int

open cur_table1   --打开游标

fetch next from cur_table1 to @KHMC,@SPDM,@DJ,@SL,@XSSL   --取一条记录,放到变量中

while @@FETCH_STATUS = 0   --状态正常返回0,也就是没有到游标的末尾
begin
   select @KHMC,@SPDM,@DJ,@SL,@XSSL
   
   fetch next from cur_table1 to @KHMC,@SPDM,@DJ,@SL,@XSSL
end

close cur_table1       --关闭游标
deallocate cur_table1  --释放游标资源,否则会导致内存泄露


[解决办法]


上面的一个例子是比较简单的,这个例子是复杂的例子,完整的:

我有两张表,分别是:table1
 KHMC         SPDM DJ  SL XSSL
广西骆俊峰 5609B 100.0000 12 NULL
广西骆俊峰 5609B 80.0000  7 NULL
广西骆俊峰 5609B 60.0000  6 NULL
广西骆俊峰 5609B 50.0000  13 NULL
广西骆俊峰 5609B 40.0000  21 NULL
table2
khmc         spdm sl bysl
广西骆俊峰 5609B 20 NULL

而我想要的结果是用第二张表里的数据去一行行的填充第一个表的数据(关联关系是 khmc,spdm):
 KHMC         SPDM DJ  SL XSSL
广西骆俊峰 5609B 100.0000 12 12
广西骆俊峰 5609B 80.0000  7 7
广西骆俊峰 5609B 60.0000  6 1
广西骆俊峰 5609B 50.0000  13 NULL
广西骆俊峰 5609B 40.0000  21 NULL

create table table1
(KHMC varchar(20), SPDM varchar(10), DJ varchar(10), SL int, XSSL int)

insert into table1
 select '广西骆俊峰', '5609B', '100.0000', 12, null union all
 select '广西骆俊峰', '5609B', '80.0000', 7, null union all
 select '广西骆俊峰', '5609B', '60.0000', 6, null union all
 select '广西骆俊峰', '5609B', '50.0000', 13, null union all
 select '广西骆俊峰', '5609B', '40.0000', 21, null


create table table2
(khmc varchar(20), spdm varchar(10), sl int, bysl int)

insert into table2
 select '广西骆俊峰', '5609B', 20, null
 


declare @table1_khmc varchar(10)
declare @table1_spdm varchar(20)
declare @table1_sl int
declare @table1_xssl int

--定义table1的游标
declare cur_table1 cursor
for select KHMC,SPDM,sl,xssl from table1 for update  --可以游标更新的


declare @table2_khmc varchar(10)
declare @table2_spdm varchar(20)
declare @table2_sl int


--定义table2的游标
declare cur_table2 cursor
for select khmc,spdm,sl from table2   --用于查询的游标
 

open cur_table2;  --打开游标

--从游标中取数,放到变量中
fetch next from cur_table2 into @table2_khmc,@table2_spdm,@table2_sl


while @@FETCH_STATUS = 0   --外层游标cur_table2的遍历
begin
   open cur_table1;
   fetch next from cur_table1 into @table1_khmc,@table1_spdm,@table1_sl,@table1_xssl
   
   while @@FETCH_STATUS = 0  --内存游标cur_table1的遍历
   begin
      if (@table1_khmc = @table2_khmc) and (@table2_spdm = @table1_spdm)
      begin
update table1
set xssl = case when @table2_sl >= isnull(@table1_sl,0)
                     then @table1_sl
                when @table2_sl < isnull(@table1_sl,0)
                     then @table2_sl
           end
where current of cur_table1;

--如果table2的sl大于table1的sl,那么可以继续循环,否则就退出内层有游标


if @table2_sl >= isnull(@table1_sl,0)
   set @table2_sl = @table2_sl - ISNULL(@table1_sl,0);
else
   break;
   
fetch next from cur_table1 into @table1_khmc,@table1_spdm,@table1_sl,@table1_xssl
  end
  
   end
   
   close cur_table1; --关闭内层游标
   
   fetch next from cur_table2 into @table2_khmc,@table2_spdm,@table2_sl
   
end

close cur_table2;   --关闭游标

deallocate cur_table2;  --释放游标cur_table2的资源

deallocate cur_table1;  --释放游标cur_table1的资源


--查询更新后的结果
select *
from table1
/*
KHMC    SPDMDJ      SLXSSL
广西骆俊峰5609B100.0000  1212
广西骆俊峰5609B80.0000  7    7
广西骆俊峰5609B60.0000  6    1
广西骆俊峰5609B50.0000  13NULL
广西骆俊峰5609B40.0000  21NULL
*/


[解决办法]
引用:
Quote: 引用:

这是一个相对简单的例子,就是输出每天记录的值:

create table table1
(KHMC varchar(20), SPDM varchar(10), DJ varchar(10), SL int, XSSL int)
 
insert into table1
 select '广西骆俊峰', '5609B', '100.0000', 12, null union all
 select '广西骆俊峰', '5609B', '80.0000', 7, null union all
 select '广西骆俊峰', '5609B', '60.0000', 6, null union all
 select '广西骆俊峰', '5609B', '50.0000', 13, null union all
 select '广西骆俊峰', '5609B', '40.0000', 21, null
 go
 
 
 
declare cur_table1 cursor
for select * from table1

declare @KHMC varchar(20)
declare @SPDM varchar(10)
declare @DJ varchar(10)
declare @SL int
declare  @XSSL int

open cur_table1   --打开游标

fetch next from cur_table1 to @KHMC,@SPDM,@DJ,@SL,@XSSL   --取一条记录,放到变量中

while @@FETCH_STATUS = 0   --状态正常返回0,也就是没有到游标的末尾
begin
   select @KHMC,@SPDM,@DJ,@SL,@XSSL
   
   fetch next from cur_table1 to @KHMC,@SPDM,@DJ,@SL,@XSSL
end

close cur_table1       --关闭游标
deallocate cur_table1  --释放游标资源,否则会导致内存泄露


消息 156,级别 15,状态 1,第 10 行
关键字 'to' 附近有语法错误。
消息 156,级别 15,状态 1,第 14 行
关键字 'to' 附近有语法错误。


改了一下:
if OBJECT_ID('table1') is not null
drop table table1
go


create table table1
(KHMC varchar(20), SPDM varchar(10), DJ varchar(10), SL int, XSSL int)
  
insert into table1
 select '广西骆俊峰', '5609B', '100.0000', 12, null union all
 select '广西骆俊峰', '5609B', '80.0000', 7, null union all
 select '广西骆俊峰', '5609B', '60.0000', 6, null union all
 select '广西骆俊峰', '5609B', '50.0000', 13, null union all
 select '广西骆俊峰', '5609B', '40.0000', 21, null
 go
  
  
  
declare cur_table1 cursor
for select * from table1
 
declare @KHMC varchar(20)
declare @SPDM varchar(10)
declare @DJ varchar(10)
declare @SL int
declare  @XSSL int
 
open cur_table1   --打开游标
 
fetch next from cur_table1 into @KHMC,@SPDM,@DJ,@SL,@XSSL   --取一条记录,放到变量中
 
while @@FETCH_STATUS = 0   --状态正常返回0,也就是没有到游标的末尾
begin
   select @KHMC,@SPDM,@DJ,@SL,@XSSL
    
   fetch next from cur_table1 into @KHMC,@SPDM,@DJ,@SL,@XSSL
end
 
close cur_table1       --关闭游标
deallocate cur_table1  --释放游标资源,否则会导致内存泄露


[解决办法]
http://www.tuicool.com/articles/vA3m6bA
这个不错 很简单
[解决办法]

--申明一个游标
DECLARE MyCursor CURSOR
FOR SELECT TOP 5 FBookName,FBookCoding FROM TBookInfo

--打开一个游标
OPEN MyCursor

--循环一个游标
DECLARE @BookName nvarchar(2000),@BookCoding nvarchar(2000)
FETCH NEXT FROM  MyCursor INTO @BookName,@BookCoding
WHILE @@FETCH_STATUS =0
BEGIN
print 'name'+@BookName
FETCH NEXT FROM  MyCursor INTO @BookName,@BookCoding


END

--关闭游标
CLOSE MyCursor
--释放资源
DEALLOCATE MyCursor


游标属于行级操作 消耗很大 
SQL查询是基于数据集的
所以一般查询能有 能用数据集 就用数据集 别用游标 
数据量大 是性能杀手
[解决办法]
测试3条数据

CREATE TABLE test_main (
id      INT,
value   VARCHAR(10),
PRIMARY KEY(id)
);
INSERT INTO test_main(id, value) VALUES (1, 'ONE');
INSERT INTO test_main(id, value) VALUES (2, 'TWO');
INSERT INTO test_main(id, value) VALUES (3, 'THREE');


简单循环处理

DECLARE
    @id    INT, @value VARCHAR(10);
 BEGIN
   -- 定义游标.
   DECLARE c_test_main CURSOR FAST_FORWARD FOR
     SELECT id, value FROM test_main;
   -- 打开游标.
   OPEN c_test_main;
  --填充数据.
   FETCH NEXT FROM c_test_main INTO @id, @value;
    --假如检索到了数据,才处理.
    WHILE @@fetch_status = 0
   BEGIN
     PRINT @value;
    --填充下一条数据.
    FETCH NEXT FROM c_test_main INTO @id, @value;
   END;
   -- 关闭游标
   CLOSE c_test_main;
   --释放游标.
    DEALLOCATE c_test_main;
 END;
 go


 -----结果
ONE
TWO
THREE



用于更新的游标

DECLARE
    @id    INT,  @value VARCHAR(10);
  BEGIN
   --定义游标.
   DECLARE c_test_main CURSOR FOR
      SELECT id, value FROM test_main
       FOR UPDATE;
    --打开游标.
   OPEN c_test_main;
    --填充数据.
    FETCH NEXT FROM c_test_main INTO @id, @value;
   --假如检索到了数据,才处理.
   WHILE @@fetch_status = 0
   BEGIN
      PRINT @value;
     --更新数据.
      UPDATE
       test_main
    SET
       value = value + '1'
    WHERE
       CURRENT OF c_test_main;
     --填充下一条数据.
     FETCH NEXT FROM c_test_main INTO @id, @value;
   END;
   --关闭游标
    CLOSE c_test_main;
    --释放游标.
   DEALLOCATE c_test_main;
  END;
 go

[解决办法]
引用:
declare testCursor cursor scroll for 
select sno,score from sc for update of score 
declare @sno varchar(50),@score int 
open testcursor 
fetch next from testcursor into @sno,@score
while @@fetch_status = 0
begin
if @score < 60 
select @sno,@score
update sc set score = 60 where  current of testcursor
fetch next from testcursor into @sno,@score
end
close testcursor
deallocate testcursor

这里我想分数低于60的更新成60分 这里会把所有都更新成60分了,请问那里错!解答完结贴!



declare testCursor cursor scroll for 
select sno,score from sc for update of score 

declare @sno varchar(50),@score int 

open testcursor 

fetch next from testcursor into @sno,@score

while @@fetch_status = 0
begin
if @score < 60 
begin
select @sno,@score
update sc set score = 60 where  current of testcursor  --小于60,就修改,否则不修改
end
fetch next from testcursor into @sno,@score
end

close testcursor
deallocate testcursor

热点排行