原文:https://www.cnblogs.com/swq6413/archive/2012/09/01/2667190.htmlhtml
在编写SQL批处理或存储过程代码的过程当中,常常会碰到有些业务逻辑的处理,须要对知足条件的数据记录逐行进行处理,这个时候,你们首先想到的方案大部分是用“游标”进行处理。数据库
举个例子,在订单管理系统中,客服须要对订单日期为2012-09-01的销售订单进行某个批量操做,好比批量发货操做,后台业务逻辑处理时,须要对知足条件的订单记录进行逐行处理。测试
我首先是采用“游标”编写的业务逻辑存储过程,SQL代码能够以下:spa
游标 DECLARE @ORDERID VARCHAR(30) -- 声明局部游标:从订单数据表获取订单日期为2012-09-01,订单类型为Sales的订单编号 DECLARE CURSOR_ORDER CURSOR LOCAL FOR SELECT ORDERID FROM ORDERHD H WHERE ORDERDATE = '2012-09-01' AND H.ORDERTYPE = 'Sales' -- 打开游标 OPEN CURSOR_ORDER FETCH NEXT FROM CURSOR_ORDER INTO @ORDERID WHILE @@FETCH_STATUS = 0 BEGIN /* 此处编写对当前行数据的业务逻辑处理代码 */ -- 获得下一条记录 FETCH NEXT FROM CURSOR_ORDER INTO @ORDERID END -- 关闭游标 CLOSE CURSOR_ORDER -- 释放游标 DEALLOCATE CURSOR_ORDER
功能是实现了,可是客服在实际使用过程当中,常常反馈批量操做效率太慢,须要等待较长时间才能完成操做。通过测试发现,速度慢在游标逐行处理过程当中,当须要处理的记录数较大,并且游标处理位于数据库事务内时,速度很是慢。code
那么,有什么方法能够解决这个处理速度慢的问题吗?htm
经不断的尝试,终于找到一个方法,那就是用WHILE循环来进行逐行数据处理。首先将须要处理的数据记录获取到一个临时表(此临时表包括2个重要字段:REFID - 记录行号,DealFlg:行处理标识,用1/0标识行是否已处理),而后WHILE循环对临时表进行逐行处理,SQL代码以下:blog
While 循环 DECLARE @REFID INT , @ORDERID VARCHAR(30) -- 获取待处理的数据记录到临时表 -- 字段说明:REFID:记录行号 / DealFlg:行处理标识 SELECT REFID = IDENTITY(INT , 1, 1), DealFlg = 0, ORDERID INTO #Temp_Lists FROM ORDERHD WHERE ORDERDATE = '2012-09-01' AND H.ORDERTYPE = 'Sales' -- 获取临时表数据的最小行号 SELECT @REFID = MIN(REFID) FROM #Temp_Lists WHERE DealFlg = 0 -- 若最小行号不为空(有须要处理的数据) WHILE @REFID IS NOT NULL BEGIN -- 获取当前处理行的信息 SELECT @ORDERID = ORDERID FROM #Temp_Lists WHERE REFID = @REFID /* 此处编写对当前行数据的业务逻辑处理代码 */ -- 标识当前行已处理完毕 UPDATE #Temp_Lists SET DealFlg = 1 WHERE REFID = @REFID -- 选择下一行号 SELECT @REFID = MIN(REFID) FROM #Temp_Lists WHERE DealFlg = 0 AND REFID > @REFID END
通过这样对原存储过程进行修正后,批量操做速度获得显著提高。事务
有兴趣的朋友,能够尝试使用这个方法替代游标,对比2种方案的处理效率。class