您的位置:首页 > 数据库

Day 8(11.15):游标

2015-11-15 17:04 232 查看
--  ****************************************************

-- 游标

/*

在一个关系中,如果没有一个字段可以按照顺序来标识每一个记录,

很难按照记录间的前后顺序来定位到上一条或下一条记录,也很难对关系中的每个记录逐个处理;

游标可以用来解决这个问题。

*/

-- n.1 --------------------------------------------------

-- 游标简介

DECLARE cursor_name CURSOR FOR select * from pubs.dbo.authors -- 定义游标的名称,定义游标结果集的 SELECT 语句

OPEN cursor_name                                              -- 打开游标

FETCH next FROM cursor_name                                   -- 在游标中检索特定的一行(这里的 next 指下一行)

CLOSE cursor_name                                             -- 关闭游标(对应于 OPEN )

DEALLOCATE cursor_name                                        -- 释放游标(对应于 DECLARE )

-- n.2 --------------------------------------------------

-- 使用游标来逐行更新每一条记录

/*

use Test

Go

create table dbo.t_emp_mgr

(

emp varchar(30) primary key,

mgr varchar(30) NULL foreign key references t_emp_mgr(emp),

NoOfReports int DEFAULT 0

)

insert t_emp_mgr(emp, mgr) values ('Harry', NULL)

insert t_emp_mgr(emp, mgr) values ('Alice', 'Harry')

insert t_emp_mgr(emp, mgr) values ('Paul', 'Alice')

insert t_emp_mgr(emp, mgr) values ('Joe', 'Alice')

insert t_emp_mgr(emp, mgr) values ('Dave', 'Joe')

select * from t_emp_mgr

要求计算出 t_emp_mgr 表的 NoOfReports 值(NoOfReports 为所在记录的员工的直接下属人数)

*/

declare my_cursor cursor

for select emp from t_emp_mgr  -- 注意这里不是 * 而是一个字段,配合下面的 INTO 子句

open my_cursor

declare @emp varchar(30)       -- 定义一个变量,用于保存当前游标中的 emp 值

fetch next from my_cursor into @emp  -- 第一次使用 FETCH next 即指向结果集的第一行(INTO 关键字将游标中的结果集保存在变量中)

while @@fetch_status=0               -- 最近一个 FETCH 语句成功,被检索的行存在

  begin

     update t_emp_mgr set NoOfReports=(select count(*) from t_emp_mgr where mgr=@emp) where current of my_cursor -- WHERE CURRENT OF cursor_name 定位当前行,用于更新或删除

     fetch next from my_cursor into @emp  -- 第 n 次使用 FETCH next,即指向下一行

  end

close my_cursor

deallocate my_cursor           -- 不要忘记关闭和释放游标

-- n.3 --------------------------------------------------

-- 使用游标来随即访问记录

/*

select * from pubs.dbo.employee

公司周年庆,随即抽取幸运员工发送奖品

*/

declare my_cursor scroll cursor                -- SCROLL 关键字允许在 FETCH 语句中随意定位行,否则只能使用 FETCH next

for select * from pubs.dbo.employee

open my_cursor

declare @n int   

select @n=convert(int,rand()*@@cursor_rows+1)  -- 获得随机数,范围从 1 到 @@cursor_rows (系统变量 @@cursor_rows = 最近一个打开的游标中填充的行数)

fetch absolute @n from my_cursor               -- 使用 FETCH ABSOLUTE n 语句来定位游标中的绝对位置

close my_cursor

deallocate my_cursor                           -- 不要忘记关闭和释放游标

-- n.4 --------------------------------------------------

-- 使用游标变量来向存储过程传递参数

/*

使用 DECLARE 和 OPEN 局部游标的存储过程可以将游标传递出去以供要求调用的存储过程、触发器或批处理使用。

这可以通过使用由新的 CURSOR VARYING 数据类型定义的 OUTPUT 参数来实现。游标变量只能用作 OUTPUT 参数。不能将它们用于输入参数。

当存储过程完成时游标必须是打开的,以便将游标返回 OUTPUT 参数。

-- 创建用于输出游标变量的存储过程

create proc dbo.p_GetCursor

@outCursor CURSOR VARYING output 

as

SET @outCursor = CURSOR FOR

select au_lname from pubs.dbo.authors where au_lname like 'S%'

OPEN @outCursor

Go

-- 定义一个游标变量

declare @cursorVar cursor

-- 执行存储过程,填充游标变量 @cursorVar

exec dbo.p_GetCursor @outCursor = @cursorVar output

-- 使用游标变量来检索结果

fetch next from @cursorVar

while @@fetch_status = 0

   begin

      fetch next from @cursorVar

   end

close @cursorVar

deallocate @cursorVar

*/

-- 练习 --------------------------------------------------

-- 1 使用游标,隔行输出 pubs.dbo.authors 表中的记录

-- 2 使用游标,对 1/4 的用户,升级电话号码,对于首位 >= 6 的号码,在号码前添加一位 ‘5’,否则添加‘6’

/*

use Test

Go

create table dbo.t_phone(home_id uniqueidentifier,phone_num varchar(10))

Go

declare @i int

set @i=1

while @i<=200

   begin

      insert t_phone values (newid(),substring(convert(varchar,rand()),3,5)+substring(convert(varchar,rand()),3,2))

      set @i=@i+1

   end 

select * from t_phone

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  sql server 数据库