•使用游标
•使用表变量
•使用临时表

  在数据库开发过程中,我们经常会碰到要遍历数据表的情形,一提到遍历表,我们第一印象可能就想到使用游标,使用游标虽然直观易懂,但是它不符合面向集合操作的原则,而且性能也比面向集合低。当然,从面向集合操作的角度出发,也有两种方法可以进行遍历表的操作,总结起来,遍历表有下面几种方法。
1.使用游标
2.使用表变量
3.使用临时表

我的需求是:针对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--类似 declare @a int; 

 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


set rowcount * 使 SQL Server 在返回指定的行数之后停止处理查询。
要将此选项设置为 off 以便返回所有的行,请将 SET ROWCOUNT 指定为 0。
复制代码

回到顶部

使用临时表

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


复制代码

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