SQL基础理论篇(十二):游标

简介

sql编程与传统编程最大的区别之一,就是sql是面向集合的思考方式,更加关注“获取什么”,而不是如何获取。因为sql本身是以关系模型和集合论作为基础的。

在有的情况下,我们不需要对查询结果集中的所有数据行都采用相同的处理,而只是每次处理一行或者一部分行,这时候就需要面向过程编程。

游标就是这种编程方式的体现,或者说是SQL为了实现面向过程而做的一个扩充(其实应用面不大)。如果你有面向过程编程的经验的话,对于游标的理解会更容易一些。

我们需要关注的几个问题:

  • 什么是游标?我们为什么要使用游标?
  • 如何使用游标?
  • 日常中使用游标的案例。

看完下面对游标的介绍,其实大概能得出结论,游标一般适用的是那种需要对不同类型数据行做不同处理的场景,或者是某行的更新需要按照前面的行来进行的场景,相对应用面比较窄。

而且游标对性能的影响也比较大,比如说在使用的过程中,会对数据行进行加锁(有时关闭游标时才会释放),比较会影响效率,另外它的操作都是在内存中进行的,因此对资源的消耗也比较大。

再就是写起来也费劲。

所以现实的生产环境里一般也不会用游标,可以考虑使用case when或者Python等编程语言来替代。因此本节只是从教程里摘取了部分知识点,做简单的介绍,对原理并没有深入。

什么是游标

教程的评论里,有个老哥写的很好,深以为然,他说他更倾向于使用case的方式来处理例子里的业务,但是游标也有自己不可被替代的场景,即,如果某行的更新需要根据前面的行数据来做时,游标就会更加适用。

使用游标会降低查询性能,如无必要,不要使用游标。

在SQL里,游标是一种临时的数据库对象,它其实是数据表中的数据行指针,没错,就是我们在编程时通常理解的那个指针。

如何使用游标

大概有五步。在不同DBMS里,使用游标的语法会有不同,这里主要以MySQL举例来讲。

第一步,定义游标。

MySQL、SQL Server、DB2和MarinaDB里是这么写:

DECLARE cursor_name CURSOR FOR select_statement

而Oracle和PostgreSQL,是写成:

DECLARE cursor_name CURSOR IS select_statement

这里的select_statement就是指需要执行的select语句,但是这里还没开始遍历数据。

比如说,我想定义一个能存储heros表中最大生命值的游标,可以写成:

DECLARE cur_hero CURSOR FOR 
  SELECT hp_max FROM heros;

第二步,打开游标:

OPEN cursor_name

打开游标的时候,select语句就会被执行,并把查询结果集发送到游标工作区(在内存)。

第三步,从游标中取得数据:

FETCH cursor_name INTO var_name ...

这句的意思是,使用cursor_name这个游标读取当前行,并将数据保存到var_name这个变量里,最后,游标自动++,指到下一行。

如果游标读取的数据行有多个列,那么在into后面多写几个变量名,逗号隔开就行。

这句话一般是放在循环里循环执行的。

第四步,关闭游标:

CLOSE cursor_name

游标关闭后就不能使用了。再使用的话,只能重新打开。

第五步,释放游标:

DEALLOCATE cursor_namec 

主动释放内存资源。

接下来,抄一下教程里给出的游标应用示例,即用游标来扫描heros数据表中的数据行,并累计生命值字段,输出。

CREATE PROCEDURE `calc_hp_max`()
BEGIN
       -- 创建接收游标的变量
       DECLARE hp INT;  

       -- 创建总数变量 
       DECLARE hp_sum INT DEFAULT 0;
       -- 创建结束标志变量  
     DECLARE done INT DEFAULT false;
       -- 定义游标     
       DECLARE cur_hero CURSOR FOR SELECT hp_max FROM heros;
       -- 指定游标循环结束时的返回值  
     DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = true;  
       
       OPEN cur_hero;
       read_loop:LOOP 
       FETCH cur_hero INTO hp;
       -- 判断游标的循环是否结束,否则游标到最后一行时再++会报错
       IF done THEN  
                     LEAVE read_loop;
       END IF; 
              
       SET hp_sum = hp_sum + hp;
       END LOOP;
       CLOSE cur_hero;
       SELECT hp_sum;
END

当然,上面的案例只是用来介绍下游标具体是怎么用的,如果真的想完成求累加和的目的的话,直接sum就可以了。

参考文献

  1. 16丨游标:当我们需要逐条处理数据时,该怎么做?
  2. MySQL ------ 游标(CURSOR)(二十六)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值