SQL Server中几种遍历方式比较
SQL遍历解析
在SQL的存储过程,函数中,经常需要使用遍历(遍历table),其中游标、临时表等遍历方法很常用。面对小数据量,这几种遍历方法均可行,但是面临大数据量时,就需要择优选择,不同的遍历方法,在效率上存在指数级别的差异
本文列举了常用的3中遍历方法:游标、临时表、索引表,重点分析其效率。
本文主要针对大量数据的遍历,当数据量小时;可以随意选择一种遍历方法。
实例数据如下:一共177471条数据

需求:更新LDBM,其中LDBM=LXBM+LDXLH;即update V_TL_T_LD_ALL set LDBM=LXBM+LDXLH:为了演示遍历,我们循环遍历,一条条数据更新,同时统计其效率,并初略分析其原因
1.游标遍历
游标的遍历
游标是一种最常用的方法,使用起来比较简单,主要步骤为:声明游标,打开游标,使用游标,关闭游标和释放游标。示例代码如下
-- 方法1:游标
-- 声明变量
DECLARE
@LDBM AS NVARCHAR(20),
@LDXLH AS NVARCHAR(20),
@LXBM AS NVARCHAR(20),
@CROWID AS NVARCHAR(80); -- 声明游标
DECLARE T_LD CURSOR FAST_FORWARD FOR
SELECT LDBM,LDXLH,LXBM,CROWID
FROM V_TL_LD_ALL1 OPEN T_LD; -- 取第一条记录
FETCH NEXT FROM T_LD INTO @LDBM,@LDXLH,@LXBM,@CROWID; WHILE @@FETCH_STATUS=0
BEGIN
-- 操作
UPDATE V_TL_LD_ALL1 SET LDBM= @LDBM+' '+@LDXLH WHERE CROWID=@CROWID; -- 取下一条记录
FETCH NEXT FROM T_LD INTO @LDBM,@LDXLH,@LXBM,@CROWID;
END -- 关闭游标
CLOSE T_LD; -- 释放游标
DEALLOCATE T_LD;
游标是最直接的从表里面一条条的数据取出,并进行update操作,没有涉及到索引,如果数据量大,其取数据和update都将消耗大量的时间,因此此种方式效率很低。
从对数据库的操作上,其一共操作数据库2n+1次,将数据取出并存入游标(申明游标):1次;update更新操作:n次;从游标取记录:n次;将数据存储到游标和消耗了大量的内存,且随着数据量的增大,消耗值将呈现指数增加
更新上述177474条数据一共消耗了2h48min37s
2.临时表
使用游标不仅仅存在性能的问题,也违背面向集合思想的问题,所以我们有必要用面向集合的思想去找到一种更好的解决方案,即使用面向对象的思想,构造一个临时表,然后直接操作临时表,代码如下。
-- 方法2:使用临时表
-- 创建临时表
SELECT LDBM,LDXLH,LXBM,CROWID
INTO #T_LD
FROM V_TL_LD_ALL1 -- 声明变量
DECLARE
@LDBM AS NVARCHAR(20),
@LDXLH AS NVARCHAR(20),
@LXBM AS NVARCHAR(20),
@CROWID AS NVARCHAR(80); WHILE EXISTS(SELECT CROWID FROM #T_LD)
BEGIN
-- 也可以使用top 1
SET ROWCOUNT 1
SELECT @LXBM= LXBM, @LDXLH= LDXLH,@CROWID=CROWID FROM #T_LD;
UPDATE V_TL_LD_ALL1 SET LDBM= @LXBM+' '+@LDXLH WHERE CROWID=@CROWID;
SET ROWCOUNT 0 DELETE FROM #T_LD WHERE CROWID=@CROWID;
END
使用临时表,和游标类似,同时将大量的数据存储到内存中,但是随着遍历的进行,临时表的数据量越来越小,可以相当程度的降低内存的消耗,但是需要不停的与table表做交互,一共操作3n+1次数据库;
此种方式,更新上述数据一共消耗:1H:45min:37S
3.索引表
索引表和临时表的操作类似;唯一区别在于在建立临时表是,添加一个索引,然后通过此索引从表中取数据;效率上有所提升,但是增加了变量的输出,代码如下
--方法3:使用索引表
--创建临时表
IF EXISTS(Select Name From Sysobjects Where Name='tmpTable')
DROP table tmpTable --存在则删除
create table tmpTable(
NID int primary key identity(1,1), --主键,自增
CrowId nvarchar(90),
LXBM nvarchar(20),
LDXLH nvarchar(6),
)
--插入数据
insert into tmpTable(CrowId,LXBM,LDXLH)
select CrowId,LXBM,LDXLH from V_TL_LD_ALL1 -- 声明变量
DECLARE
@index int,
@countNum int,
@LDBM AS NVARCHAR(20),
@LDXLH AS NVARCHAR(20),
@LXBM AS NVARCHAR(20),
@CROWID AS NVARCHAR(80); select @countNum=count(1) from tmpTable;
set @index=0;
--遍历
while @index<@countNum
begin
set @index=@index+1;
select @LXBM= LXBM, @LDXLH= LDXLH,@CROWID=CROWID from tmpTable where NID=@index
UPDATE V_TL_LD_ALL1 SET LDBM= @LXBM+' '+@LDXLH WHERE CROWID=@CROWID;
end --删除临时索引表
DROP table tmpTable
临时索引表和临时表类似,区别在于:在取数据的时候,通过索引的方式取数据;相比临时表,减少了频繁操作数据库的次数,相比游标,减少了与数据库交互的时间(索引检索速度更快)
更新上述数据,一共消耗:1H2,min
比较而言,建议尽可能少的使用游标,不仅消耗内存,代码量也稍微复杂一些;当数据量小的时候,建议使用临时表(代码比较轻量),而随着数据的增加,建议使用索引表
SQL Server中几种遍历方式比较的更多相关文章
- Sql Server中的表访问方式Table Scan, Index Scan, Index Seek
1.oracle中的表访问方式 在oracle中有表访问方式的说法,访问表中的数据主要通过三种方式进行访问: 全表扫描(full table scan),直接访问数据页,查找满足条件的数据 通过row ...
- 转:Sql Server中的表访问方式Table Scan, Index Scan, Index Seek
0.参考文献 Table Scan, Index Scan, Index Seek SQL SERVER – Index Seek vs. Index Scan – Diffefence and Us ...
- HashMap 中7种遍历方式的性能分析
随着 JDK 1.8 Streams API 的发布,使得 HashMap 拥有了更多的遍历的方式,但应该选择那种遍历方式?反而成了一个问题. 本文先从 HashMap 的遍历方法讲起,然后再从性能. ...
- Sql Server中三种字符串合并方法的性能比较
文章来自:博客园-DotNet菜园 最近正在处理一个合并字符吕的存储过程,在一个测试系统的开发中,要使用到字符串合并功能,直接在Sql中做.示例:有表內容﹕名称 內容1 abc1 ...
- SQL Server的三种分页方式
直接上代码 --top not in方式 select top 条数 * from tablename where Id not in (select top 条数*页数 Id from tablen ...
- SQL Server中使用md5的方式
在SQl2005下自带的函数hashbytes() ,此函数是微软在SQL SERVER 2005中提供的,可以用来计算一个字符串的 MD5 和 SHA1 值,使用方法如下: --获取123456的M ...
- OC中四种遍历方式
标准的C语言for循环.Objective-C 1.0出现的NSEnumerator.Objective-C 1.0出现的for in快速遍历.块遍历. 遍历的话,一般是NSArray.NSDicti ...
- SQL Server 中几种常见的约束关系
1.创建唯一约束 当表中已创建主键,但又要保证其他数据列的值唯一时,可以使用唯一约束,并且唯一约束允许NULL值(只有一个) (1)展开指定的数据库: (2)右击要创建唯一约束的表,在弹出的快捷菜单中 ...
- Sql Server 中使用日期遍历
一个存储过程小案例,内容如下: declare @dt datetime set @dt='2016-01-01' while (@dt<='2016-12-31') begin -- 转换字符 ...
随机推荐
- ubuntu 16.04卸载不必要默认安装软件
两个办法,一个在ubuntu软件里一个一个删,明显的windows下做法. 还有一个通过终端来删除.ctrl+alt+t打开终端. 1.卸载libreoffices(要删一起删了,然后去装office ...
- 分布式服务框架介绍:最成熟的开源NIO框架Netty
尽管JDK提供了丰富的NIO类库,网上也有很多NIO学习例程,但是直接使用Java NIO类库想要开发出稳定可靠的通信框架却并非易事,原因如下: 1)NIO的类库和API繁杂,使用麻烦,你需要熟练掌握 ...
- [Swift]LeetCode205. 同构字符串 | Isomorphic Strings
Given two strings s and t, determine if they are isomorphic. Two strings are isomorphic if the chara ...
- [Swift]LeetCode679. 24点游戏 | 24 Game
You have 4 cards each containing a number from 1 to 9. You need to judge whether they could operated ...
- [Swift]LeetCode982. 按位与为零的三元组 | Triples with Bitwise AND Equal To Zero
Given an array of integers A, find the number of triples of indices (i, j, k) such that: 0 <= i & ...
- [Swift]LeetCode353. 设计贪吃蛇游戏 $ Design Snake Game
Design a Snake game that is played on a device with screen size = width x height. Play the game onli ...
- python网络-TFTP客户端开发(25)
一. TFTP协议介绍 TFTP(Trivial File Transfer Protocol,简单文件传输协议) 是TCP/IP协议族中的一个用来在客户端与服务器之间进行简单文件传输的协议 特点: ...
- 【Scala篇】--Scala中集合数组,list,set,map,元祖
一.前述 Scala在常用的集合的类别有数组,List,Set,Map,元祖. 二.具体实现 数组 1.创建数组 new Array[Int](10) 赋值:arr(0) = xxx Array[ ...
- 【Git】(2)---checkout、branch、log、diff、.gitignore
常用命令 一.命令 1.checkout 切换分支 git checkout 分支名 #切换分支 #如果在当前分支上对文件进行修改之后,没有commit就切换到另外一个分支b, 这个时候会报错,因为没 ...
- 代理自动配置文件PAC的使用方法
我通常上网使用两个浏览器,safari用于一般上网:Chrome安装SwitchyOmega插件,在不同的代理中切换,来保证某些网站的上网速度. 但是这种方式到了手机上就有点懵,几乎所有的iPhone ...