sqlserver 表循环-游标、表变量、临时表
在数据库开发过程中,我们经常会碰到要遍历数据表的情形,一提到遍历表,我们第一印象可能就想到使用游标,使用游标虽然直观易懂,但是它不符合面向集合操作的原则,而且性能也比面向集合低。当然,从面向集合操作的角度出发,也有两种方法可以进行遍历表的操作,总结起来,遍历表有下面几种方法。
- 使用游标
- 使用表变量
- 使用临时表
我的需求是:针对HR.Employees表,新增一列fullname,并取值firstname+lastname。
- -- 需求是,新增一列fullname,取值firstname+lastname
- ALTER TABLE HR.Employees ADD fullname NVARCHAR(30) NULL;
- GO
原始效果如下图。
这个需求本来可以一条sql语句搞定,如下代码所示。但是为了演示表的遍历,我还是使用了这三种方式来实现一下。
- USE TSQLFundamentals2008;
- GO
- UPDATE HR.Employees SET fullname= firstname+' '+lastname;
使用游标
使用游标的代码比较繁琐,概括起来主要有以下几个步骤,声明游标,打开游标,使用游标,关闭游标和释放游标。示例代码如下。

- -- 方法1:游标
- -- 声明变量
- DECLARE
- @empid AS INT,
- @firstname AS NVARCHAR(10),
- @lastname AS NVARCHAR(20);
- -- 声明游标
- DECLARE C_Employees CURSOR FAST_FORWARD FOR
- SELECT empid,firstname,lastname
- FROM HR.Employees
- ORDER BY empid;
- OPEN C_Employees;
- -- 取第一条记录
- FETCH NEXT FROM C_Employees INTO @empid,@firstname,@lastname;
- WHILE @@FETCH_STATUS=0
- BEGIN
- -- 操作
- UPDATE HR.Employees SET fullname= @firstname+' '+@lastname WHERE empid=@empid;
- -- 取下一条记录
- FETCH NEXT FROM C_Employees INTO @empid,@firstname,@lastname;
- END
- -- 关闭游标
- CLOSE C_Employees;
- -- 释放游标
- DEALLOCATE C_Employees;

运行脚本,效果如下图。
可以看到,已经达到我们想要的效果了。
使用表变量
因为使用游标存在性能和违背面向集合思想的问题,所以我们有必要用面向集合的思想去找到一种更好的解决方案,下面这种方法是使用表变量的方式实现的,代码如下。

- 1 -- 方法2:使用表变量
- 2 -- 声明表变量
- 3 DECLARE @temp TABLE
- 4 (
- 5 empid INT,
- 6 firstname NVARCHAR(10),
- 7 lastname NVARCHAR(20)
- 8 );
- 9
- 10 -- 将源表中的数据插入到表变量中
- 11 INSERT INTO @temp(empid, firstname, lastname )
- 12 SELECT empid,firstname,lastname FROM HR.Employees
- 13 ORDER BY empid;
- 14
- 15 -- 声明变量
- 16 DECLARE
- 17 @empid AS INT,
- 18 @firstname AS NVARCHAR(10),
- 19 @lastname AS NVARCHAR(20);
- 20
- 21 WHILE EXISTS(SELECT empid FROM @temp)
- 22 BEGIN
- 23 -- 也可以使用top 1
- 24 SET ROWCOUNT 1
- 25 SELECT @empid= empid, @firstname= firstname,@lastname= lastname FROM @temp;
- 26 UPDATE HR.Employees SET fullname= @firstname+' '+@lastname WHERE empid=@empid;
- 27 SET ROWCOUNT 0
- 28
- 29 DELETE FROM @temp WHERE empid=@empid;
- 30 END

使用临时表
临时表也可以实现表变量的功能,所以我们也可以使用临时表来实现这个需求,代码如下。

- 1 -- 方法3:使用临时表
- 2 -- 创建临时表
- 3 IF OBJECT_ID('tempdb.dbo.#tempemployees','U') IS NOT NULL DROP TABLE dbo.#tempemployees;
- 4 GO
- 5
- 6 SELECT empid,firstname,lastname
- 7 INTO dbo.#tempemployees
- 8 FROM HR.Employees
- 9 ORDER BY empid;
- 10
- 11 --SELECT * FROM dbo.#tempemployees;
- 12
- 13 -- 声明变量
- 14 DECLARE
- 15 @empid AS INT,
- 16 @firstname AS NVARCHAR(10),
- 17 @lastname AS NVARCHAR(20);
- 18
- 19 WHILE EXISTS(SELECT empid FROM dbo.#tempemployees)
- 20 BEGIN
- 21 -- 也可以使用top 1
- 22 SET ROWCOUNT 1
- 23 SELECT @empid= empid, @firstname= firstname,@lastname= lastname FROM dbo.#tempemployees;
- 24 UPDATE HR.Employees SET fullname= @firstname+' '+@lastname WHERE empid=@empid;
- 25 SET ROWCOUNT 0
- 26
- 27 DELETE FROM dbo.#tempemployees WHERE empid=@empid;
- 28 END

当然,实现的效果都是一样的。
转载:
https://www.cnblogs.com/mcgrady/p/4182486.html
sqlserver 表循环-游标、表变量、临时表的更多相关文章
- SQL Server循环——游标、表变量、临时表
游标 在游标逐行处理过程中,当需要处理的记录数较大,而且游标处理位于数据库事务内时,速度非常慢. -- 声明变量 DECLARE @Id AS Int -- 声明游标 DECLARE C_Id CUR ...
- sql循环-游标、临时表、表变量
游标 在游标逐行处理过程中,当需要处理的记录数较大,而且游标处理位于数据库事务内时,速度非常慢. -- 声明变量 DECLARE @Id AS Int -- 声明游标 DECLARE C_Id CUR ...
- 使用whIle循环语句和变量打印九九乘法表
-设置i变量declare @i int --设置j变量declare @j int --设置乘法表变量declare @chengfabiao varchar(1000)--给i,j,@chengf ...
- SQLSERVER和ORACLE系统表获取表名 列名以及列的注释
在工作中从数据库取的数据要导出来,但是发现导出的EXCEL中列名都是字段名(英文),为此搜集资料怎么把字段名变为中文名称,而发现ORACLE和SQLSERVER(用的SQLSERVER2008R2)又 ...
- 获取SQLSERVER所有库 所有表 所有列 所有字段信息
最近想起来做一个项目代码生成器,直接生成底层代码.. 这免不了要先行读取数据库已有的信息.. 废话不多说..开整.. SELECT NAME FROM MASTER..SYSDATABASES --读 ...
- SQL-Server数据库学习笔记-表
1. 表及其属性 表(Table):也称实体,是存储同类型数据的集合. 列(Field):也称字段.域或属性,它构成表的架构,具体表示为一条信息中的一个属性. 行(Row):也称元组(Tuple),存 ...
- oracle 删除用户,表空间;循环删除表
select * from dba_tablespaces 说明:查看所有表空间 ----------------------------------------------------------- ...
- SqlServer查询数据库所有表
//SqlServer查询数据库所有表SELECT * FROM SYSOBJECTS WHERE TYPE='U' and name like '%dict%'
- 通过修改注册表设置windows环境变量
开发环境搭建每次都要设置很多环境变量, 一般是通过 [菜单]->[计算机]->[属性]->[高级设置]->[环境变量]进行设置,重装系统后,每次都要设置很多环境变量,很麻烦. ...
随机推荐
- 《Java编程思想第四版》第 16 章 设计范式-提到观察者模式
在由Gamma,Helm 和 Johnson 编著的<Design Patterns>一书中被定义成一个“里程碑”.那本书列出了解决这个问题的 23 种不同的方法 16.1.2 范式分类 ...
- 阿里的fastJson.jar jsonArray 和 list 互转
阿里的fastJson.jar: //list转换为json List<CustPhone> list = new ArrayList<CustPhone>(); String ...
- 函数的if--while流程控制
一.流程控制---if 1.if条件判断 age=18 hight=1.70 sex="female" is_beautiful=True if sex=="female ...
- shell脚本的小记
作者:邓聪聪 mysql的脚本执行 #!/bin/sh HOST="127.0.0.1" PORT=" UESRNAME="root" PASSWOR ...
- EF的三种数据加载方式
EF的关联实体加载有三种方式:Lazy Loading,Eager Loading,Explicit Loading,其中Lazy Loading和Explicit Loading都是延迟加载. (一 ...
- Python-Django 模型层-多表查询-2
-related_name:基于双下划线的跨表查询,修改反向查询的字段 -related_query_name:基于对象的跨表查询,修改反向查询字段 publish = ForeignKey(Blog ...
- 做GUI的随笔
用的SDL库 官方网站是:https://littlevgl.com/ 改网站需要FQ 字库制作网站: https://debugdump.com/t_771.html
- django 实战篇之路由层
路由层 如何给网页添加首页及尾页 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'test',views.test), url(r'te ...
- select2 下拉搜索控件
1.添加相应的script链接 jquery: <script type="text/javascript" src="http://cdn.bootcss.com ...
- [转] 扩展微信小程序框架功能
通过第三方 JavaScript 库,扩展微信小程序框架功能. 扩展微信小程序框架功能(1)——Promise ES6 对 Promise 有了原生的支持,但微信开发者工具更新版本(0.11.1122 ...