Transact-SQL让人快遗忘的游标
Posted lonelyxmas
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Transact-SQL让人快遗忘的游标相关的知识,希望对你有一定的参考价值。
原文:【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 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
- */
以上是关于Transact-SQL让人快遗忘的游标的主要内容,如果未能解决你的问题,请参考以下文章