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中几种遍历方式比较的更多相关文章

  1. Sql Server中的表访问方式Table Scan, Index Scan, Index Seek

    1.oracle中的表访问方式 在oracle中有表访问方式的说法,访问表中的数据主要通过三种方式进行访问: 全表扫描(full table scan),直接访问数据页,查找满足条件的数据 通过row ...

  2. 转: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 ...

  3. HashMap 中7种遍历方式的性能分析

    随着 JDK 1.8 Streams API 的发布,使得 HashMap 拥有了更多的遍历的方式,但应该选择那种遍历方式?反而成了一个问题. 本文先从 HashMap 的遍历方法讲起,然后再从性能. ...

  4. Sql Server中三种字符串合并方法的性能比较

    文章来自:博客园-DotNet菜园 最近正在处理一个合并字符吕的存储过程,在一个测试系统的开发中,要使用到字符串合并功能,直接在Sql中做.示例:有表內容﹕名称  內容1     abc1      ...

  5. SQL Server的三种分页方式

    直接上代码 --top not in方式 select top 条数 * from tablename where Id not in (select top 条数*页数 Id from tablen ...

  6. SQL Server中使用md5的方式

    在SQl2005下自带的函数hashbytes() ,此函数是微软在SQL SERVER 2005中提供的,可以用来计算一个字符串的 MD5 和 SHA1 值,使用方法如下: --获取123456的M ...

  7. OC中四种遍历方式

    标准的C语言for循环.Objective-C 1.0出现的NSEnumerator.Objective-C 1.0出现的for in快速遍历.块遍历. 遍历的话,一般是NSArray.NSDicti ...

  8. SQL Server 中几种常见的约束关系

    1.创建唯一约束 当表中已创建主键,但又要保证其他数据列的值唯一时,可以使用唯一约束,并且唯一约束允许NULL值(只有一个) (1)展开指定的数据库: (2)右击要创建唯一约束的表,在弹出的快捷菜单中 ...

  9. Sql Server 中使用日期遍历

    一个存储过程小案例,内容如下: declare @dt datetime set @dt='2016-01-01' while (@dt<='2016-12-31') begin -- 转换字符 ...

随机推荐

  1. 算法与数据结构(五) 普利姆与克鲁斯卡尔的最小生成树(Swift版)

    上篇博客我们聊了图的物理存储结构邻接矩阵和邻接链表,然后在此基础上给出了图的深度优先搜索和广度优先搜索.本篇博客就在上一篇博客的基础上进行延伸,也是关于图的.今天博客中主要介绍两种算法,都是关于最小生 ...

  2. #Java学习之路——基础阶段(第八篇)

    我的学习阶段是跟着CZBK黑马的双源课程,学习目标以及博客是为了审查自己的学习情况,毕竟看一遍,敲一遍,和自己归纳总结一遍有着很大的区别,在此期间我会参杂Java疯狂讲义(第四版)里面的内容. 前言: ...

  3. [SQL]LeetCode595. 大的国家 | Big Countries

    SQL架构 Create table If Not Exists World (name varchar(), continent varchar(), area int, population in ...

  4. [Abp 源码分析]十一、权限验证

    0.简介 Abp 本身集成了一套权限验证体系,通过 ASP.NET Core 的过滤器与 Castle 的拦截器进行拦截请求,并进行权限验证.在 Abp 框架内部,权限分为两块,一个是功能(Featu ...

  5. IIS连接数据库:数据库连接出错,请检查连接字串

    搞了一早上,在网上看了各种回答,比如:C盘下的Temp文件夹权限.CONN.asp中的数据库路径问题,都不通.最后发现是: 如果使用的是64位系统,原因有可能是没有64位Access连接驱动. 所以解 ...

  6. 我的2017OKR - 年中回顾

    自从订阅了吴军老师的<硅谷来信>之后,对其中一篇介绍Google的目标管理方法OKR的文章记忆犹新.想到自己喜欢在每年年初的时候给自己定制一些规划,于是乎了解了一下OKR并重构了一下我的2 ...

  7. asp.net core 系列 6 MVC框架路由(下)

    一.URL 生成 接着上篇讲MVC的路由,MVC 应用程序可以使用路由的 URL 生成功能,生成指向操作的 URL 链接. 生成 URL 可消除硬编码 URL,使代码更稳定.更易维护. 此部分重点介绍 ...

  8. 从锅炉工到AI专家(9)

    无监督学习 前面已经说过了无监督学习的概念.无监督学习在实际的工作中应用还是比较多见的. 从典型的应用上说,监督学习比较多用在"分类"上,利用给定的数据,做出一个决策,这个决策在有 ...

  9. asp.net mvc简单实现基于Razor的分页控件

    最近在写一些web应用了解了一下asp.net mvc发现的确好用,所以直接就干上了.不过在使用asp.net mvc的Razor模板的情况并不向传统webform那样可以使用控件.但从Razor的功 ...

  10. Asp.net Core 使用Jenkins + Dockor 实现持续集成、自动化部署(一):Jenkins安装

    2019/1/31更新,经过我一段时间的使用 建议大家的jenkins还是不要使用docker方式安装 建议大家的jenkins还是不要使用docker方式安装 建议大家的jenkins还是不要使用d ...