【Transact-SQL】让人快遗忘的游标

断了今生、忘了曾经 提交于 2019-12-11 00:04:57
原文:【Transact-SQL】让人快遗忘的游标


最初学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 intdeclare @table1_xssl int --定义table1的游标declare cur_table1 cursorfor 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 cursorfor 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*/


发布了416 篇原创文章 · 获赞 135 · 访问量 94万+
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!