最初学SQL Server的时候,当学到游标的时候,突然有了一种亲切感,因为这种通过一个while循环,一条一条的处理数据的方式,很像学过的过程式语言,与C语言很相似。

慢慢的,对一些稍微复杂一点的SQL ,往往就会想到用游标去处理。也正是因为大量使用,渐渐的,在使用的过程中,也真正体会到了游标的低效,一条一条的处理方式,在数据量很小的情况下还可以,当数据一旦很多,而处理过程又非常复杂时,往往速度就会很慢。


于是乎,慢慢的开始放弃使用游标,最后都快忘记了这个老朋友了。

今天,在论坛突然发现有人提了一个问题,希望用游标来解决,于是乎,又让我再次想起了游标。


下面是那个网友提出的问题:



我有两张表,分别是: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	    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 */