2-4 游标技术

简介:
2-4 游标技术
u       了解游标的基本概念及特点,学会使用游标的基本步骤
u       掌握两个系统全局变量:@@cursor_rows@@FETCH_ STATUS在定义游标中的作用,掌握在游标中使用FETCH获取游标技术,掌握FETCH语句使用过程中的移动关键词。
u       掌握如何使用游标修改或删除数据
u       了解如何使用递归游标遍历树算法解决家族树的问题
u       了解改进的非游标查询策略
 
游标实际上是用户在系统中开设的一个数据缓冲区,存放 SQL 语句的执行结果。到目前为止,所有的 SQL 语句是采用面向集合的方法来处理和操作数据的,是针对行的集合进行的操作。应用 WHERE 子句指出的行包含在该集合之中,必须对每一行进行同样的工作。例如:返回集合的条件行( SELECT ),改变集合中的每一行的同一个列( UPDATE ),删除集合中的每一个行( DELETE )等。
游标具体使用的过程是:游标中存放查询结果的一组记录,用户可以通过移动游标指针逐一访问记录,获得结果,并赋给主变量,交由主语言进一步处理。
游标技术的引入最根本解决的问题是替代了面向集合的数据信息操作方法,试图通过数据结构指针的方法进行数据的定位查询,这就是游标概念引入的目的。它允许每次一行的操作,基于行的内容,可以决定采取的下一步行为。
  注意:我们在使用游标之前务必清楚的了解下面的两点:
q         游标是有害的!!在实际测试中,游标的效率是正常SQL select 查询的1/501/70
q         不得不按照每次一行的方式来处理行(游标)时候的性能,开销相对于面向集合的方式来处理行的性能是巨大的。在解决使用游标之前,应该确定已经仔细分析了需求,并且无法通过别的编程方法来解决问题。某些情况下面,游标是非常有用的,但是它应当是程序设计员最后的手段,而并不应当成为第一的选择!
2-4-1 使用游标的基本步骤
使用游标共分五个步骤,分别是:声明游标,打开游标,利用游标读取、修改或删除所取的行,关闭游标,释放游标。
1. 声明游标:
为游标指定获取数据时候的 select 语句。声明的游标并不会检索任何的数据,仅仅为游标指定 select 的查询范围。
Declare  游标名称  cusor cursoroptions
For select 语句
2. 打开游标
Open    游标名称
3. 取出游标中的信息
Fetch    游标名称    into @ 变量 1  @ 变量 2
该操作将使得游标移动到下一行记录,并将游标返回的每个列的数据分别赋值给本地变量,这些变量必须预先予以声明。
4. 关闭游标
关闭游标的目的是释放数据和系统资源,但是保留 select 语句,以后还可以通过 open 方法打开( open 命令与 close 相似)。
Close      游标名称
释放游标,释放相关内存,并删除游标定义
Deallocate       游标名称
实验:建立游标的基本实验
--1:请按照下面的步骤建立游标
use school
GO
--
  
FOR
SELECT sname FROM student
--
OPEN stu_cursor
--
FETCH NEXT FROM stu_cursor
--
close stu_cursor
--
deallocate stu_cursor
2-4-2 在游标中使用 FETCH
在游标的使用中我们经常会用到两个系统全局变量: @@cursor_rows @@FETCH_ STATUS ,下面我们就这两个系统全局变量进行说明。
1. @@cursor_rows
     返回连接上最后打开的游标中当前存在的合格行的数量。
2. @@FETCH_ STATUS
会被  FETCH  语句执行的最后游标的状态,而 @@fetch_status 标量的意义是: 0—— 最近一次 fetch 命令成功的获取到一行数据; 1—— 最近一次 fetch 命令到达结果集的尾部; 2—— 最近一次获取的行不可用,该行已经被删除。
实验 1 :在简单的游标中使用  FETCH
USE school
GO
DECLARE @sname varchar(40)
DECLARE stu_cursor CURSOR
FOR
 SELECT sname FROM student 
OPEN stu_cursor
FETCH NEXT FROM stu_cursor
INTO @sname
WHILE @@FETCH_STATUS = 0
BEGIN
       PRINT '
       FETCH NEXT FROM stu_cursor    INTO @sname
END
CLOSE stu_cursor
DEALLOCATE stu_cursor
GO
刚才我们看到关键词:  FETCH NEXT 是推动游标向前移动的关键,除此以外, FETCH 还包括以下的移动关键词,如表 2-6 所示。
2-6 FETCH 移动关键词
关键字
移动位置
FIRST
数据集第一条记录
LAST
数据集末一条记录
PRIOR
前一条记录
NEXT
后一条记录
RELATIVE
按照相对位置决定移动的位置
ABSOLUTE
按照绝对位置决定移动的位置
实验 2 :在简单的游标中使用  FETCH
--1
DECLARE @sname varchar(40) --定义游标阶段
DECLARE stu_cursor CURSOR
FOR
 SELECT sname FROM student
            
--定义并打开游标阶段
declare @sname varchar(20)
FETCH NEXT FROM stu_cursor
INTO @sname
print @sname                  --读取并显示游标阶段
 
declare @sname varchar(20)
FETCH prior FROM stu_cursor
INTO @sname
print @sname
-- 小问题:系统将报错提示:“fetch: 提取类型 prior 不能用于只进游标。这是为什么?”
--2:语法改进
DECLARE @sname varchar(40)
DECLARE stu_cursor CURSOR scroll –- 注意差异之处
FOR
 ……                     --其余地方同例1一致,此处略。
--3:通过游标技术循环打印学生姓名,每个姓名之间用逗号分隔
DECLARE @sname varchar(30),@s varchar(400)
DECLARE stu_cursor CURSOR
FOR
SELECT sname FROM student
OPEN stu_cursor
FETCH NEXT FROM stu_cursor INTO @s
WHILE @@FETCH_STATUS = 0
BEGIN
   FETCH NEXT FROM stu_cursor
   INTO @sname
   set @s=ltrim(rtrim(@s))+','+ltrim(rtrim(@sname))
END
--开始打印姓名
print @s
CLOSE stu_cursor
DEALLOCATE stu_cursor   --关闭并释放游标资源
GO
-- 小问题:为什么最后一行总是重复出现呢?如何解决这个问题?
实验 3 :使用游标修改或删除数据
DECLARE abc CURSOR
FOR
    SELECT sName FROM Student
OPEN abc
GO
 
FETCH NEXT FROM abc
GO
UPDATE student SET sName = '
GO
CLOSE abc
DEALLOCATE abc
GO
实验 4 :复杂的游标查询问题 —— 使用递归游标遍历树算法解决家族树的问题
--
--
  
create procedure family_all(@me_id int)
--
as
declare @child_id int,@child_name varchar(30)
declare cchild cursor local fast_forward
--
 for
 select person_id,person_name from person  where person.father_id=@me_id or person.mother_id=@me_id
 order by date_birth
--
open cchild
fetch cchild into @child_id,@child_name
--
while @@fetch_status=0
begin
print space(@@nestlevel*2)+'+'+cast(@child_id as varchar(6))+''+@child_name
--
--@@NESTLEVEL 
     exec family_all @child_id
--
     fetch cchild into @child_id,@child_name
--
end
close cchild
deallocate cchild
exec family_all 2
  注意:
当游标较少时候,使用该算法解决遍历问题已经足够;但是当数据量较大时候,就会出现问题。主要由两个原因造成:
q         MSSQL限制存储过程循环次数最多32层。
q         性能问题。基于行的游标比基于集合的查询性能上面将慢5070倍。如果假设将500万行数据组织为12个层次,需要进行游标调用500万次,开辟500万个缓冲空间,执行500万次的select查询。
实验 5 :复杂的游标查询问题 —— 改进的非游标查询策略
--
create table familytree
(person_id int, generation int, familyline varchar(20) default '')
 
declare @generation int,@firsperson int
set @generation=1
set @firsperson=1
--
insert familytree(person_id,generation,familyline)
select @firsperson,@generation,@firsperson
 
while @@rowcount>0
 begin
 set @generation=@generation+1
 insert familytree(person_id,generation,familyline)
    select person.person_id,@generation,familytree.familyline+''+str(person.person_id,5)
    from person
    inner join familytree
    on familytree.generation=@generation-1
       and (familytree.person_id=person.mother_id
            or familytree.person_id=person.father_id)
 end
--
select * from familytree
drop table familytree




本文转自 qianshao 51CTO博客,原文链接:http://blog.51cto.com/qianshao/348298,如需转载请自行联系原作者

目录
相关文章
|
算法 Java BI
使用jmap和MAT进行堆内存分析
Java程序运行中常常会遇到各种关于内存的问题,例如内存泄漏、内存溢出、内存使用率太高等问题,如果没有合适的工具和方法,则定位问题时常常感觉难以入手。本文介绍如何使用Jmap配合MAT进行Java堆内存分析,快速定位问题。
905 0
|
弹性计算 安全 Linux
使用阿里云ECS服务器和frp配置SSH反向代理
校园网、公司内网中的设备一般是没有公网ip的,所以没办法用SSH直接连接。但是平时VSCode远程连接调调代码啥的都是通过SSH来连接的,平时不在学校或者公司的时候会很麻烦。虽然说VPN、向日葵花生壳之类的方法都能解决这个问题,但是这些方法不是麻烦就是贵或者不安全。frp只需要一台有公网ip的服务器就能实现外网SSH访问,相对来说比较简单。
|
存储 人工智能 搜索推荐
Memoripy:支持 AI 应用上下文感知的记忆管理 Python 库
Memoripy 是一个 Python 库,用于管理 AI 应用中的上下文感知记忆,支持短期和长期存储,兼容 OpenAI 和 Ollama API。
882 6
Memoripy:支持 AI 应用上下文感知的记忆管理 Python 库
|
SQL 安全 数据库
从入门到精通:Python Web安全守护指南,SQL注入、XSS、CSRF全防御!
【9月更文挑战第13天】在开发Python Web应用时,安全性至关重要。本文通过问答形式,详细介绍如何防范SQL注入、XSS及CSRF等常见威胁。通过使用参数化查询、HTML转义和CSRF令牌等技术,确保应用安全。附带示例代码,帮助读者从入门到精通Python Web安全。
284 6
|
存储 人工智能 缓存
[AI Kimi] Context Caching 正式公测,推动长文本模型降本 90%
Kimi 的上下文缓存(Context Caching)技术正式公测。该技术通过预先存储数据,显著降低了计算成本和延迟,适用于长文本模型,帮助节省高达 90% 的费用,并将首 Token 延迟降低 83%。
1017 1
|
JavaScript 数据安全/隐私保护
PostMan高级用法,接口MD5+Secret签名Sign
PostMan高级用法,接口MD5+Secret签名Sign
1199 0
|
Java Spring 容器
SpringBoot 生命周期接口详细解析
SpringBoot 生命周期接口详细解析
|
存储 缓存 JavaScript
网站性能优化实战之—— gzip (webpack, vite 开启gzip 部署)
nginx 有一个模块是 gzip 模块,然后你只要开启了,nginx就会帮你来把数据(静态资源 和 接口数据)进行压缩,然后传入到客户端,客户端来解压,然后在进行代码的读取,其实这一步就是节约带宽,减少传输的代码包的数量。从而节约传输时间。然后网站就能很快打开了。
网站性能优化实战之—— gzip (webpack, vite 开启gzip 部署)
|
存储 机器学习/深度学习 人工智能
加速开启“图智”未来,阿里云图数据库GDB V3引擎发布
随着互联网时代的快速发展,企业的数据呈现爆发式的增长,数据之间的关联也越来越复杂,图数据库应运而生。本次发布会将带你了解图数据库GDB的业务价值、典型应用场景,揭秘图数据库GDB V3引擎的设计原理、整体架构和核心数据结构,同时结合阿里巴巴集团内外部最佳实践,分享如何使用Graph + AI技术,分析各个数据源之间的关系特征,以及如何发现数据中的隐秘价值。
8647 1
加速开启“图智”未来,阿里云图数据库GDB V3引擎发布
|
消息中间件 存储 运维
AWS MSK 调研
2021 AWS Re-Invent 上发布了 MSK Serverless,本文从 Stream Storage 角度做一些调研解读。
1113 0