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
*/
-- 游标
/*
在一个关系中,如果没有一个字段可以按照顺序来标识每一个记录,
很难按照记录间的前后顺序来定位到上一条或下一条记录,也很难对关系中的每个记录逐个处理;
游标可以用来解决这个问题。
*/
-- 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
*/
相关文章推荐
- Android之获取手机上的图片和视频缩略图thumbnails
- 数据库链接字符串查询网站
- DB2实例管理
- DB2实例管理
- 保障MySQL数据安全的14个最佳方法
- mysql问答汇集
- 创建一个空的IBM DB2 ECO数据库的方法
- Access 2000 数据库 80 万记录通用快速分页类
- 开通一个数据库失败的原因的和解决办法
- 一个简单的asp数据库操作类
- CentOS下DB2数据库安装过程详解
- EasyASP v1.5发布(包含数据库操作类,原clsDbCtrl.asp)第1/2页
- sql2008 还原数据库解决方案
- Oracle 数据库自动存储管理-安装配置
- Oracle 数据库 临时数据的处理方法
- 数据库分页查询语句数据库查询
- 最近比较流行的数据库挂马
- Oracle 手动创建数据库步骤详解
- 分割超大Redis数据库例子