【mysql】游标的基本使用
虽然可以通过筛选条件和 ,或者是限定返回记录的关键字返回一条记录,但是,却无法在结果集中像指针一样,向前定位一条记录、向后定位一条记录,或者是,并对记录的数据进行处理。这个时候,就可以用到游标。游标,提供了一种灵活的操作方式,能够对结果集中的每一条记录进行定位,并对指向的记录中的数据进行操作的数据结构。游标让 SQL 这种面向集合的语言有了面向过程开发的能力。在 SQL 中,游标是一种临时的数据库
1. 什么是游标(或光标)
-
虽然可以通过筛选条件
WHERE
和HAVING
,或者是限定返回记录的关键字LIMIT
返回一条记录,但是,却无法在结果集中像指针一样,向前定位一条记录、向后定位一条记录,或者是随意定位到某一条记录
,并对记录的数据进行处理。 -
这个时候,就可以用到游标。游标,提供了一种灵活的操作方式,能够对结果集中的每一条记录进行定位,并对指向的记录中的数据进行操作的数据结构。游标让 SQL 这种面向集合的语言有了面向过程开发的能力。
-
在 SQL 中,游标是一种临时的数据库对象,可以指向存储在数据库表中的数据行指针。这里游标
充当了指针的作用
,可以通过操作游标来对数据行进行操作。 -
MySQL中游标可以在存储过程和函数中使用。
比如,查询了 employees
数据表中工资高于15000
的员工都有哪些:
SELECT employee_id,last_name,salary FROM employees
WHERE salary > 15000;
这里就可以通过游标来操作数据行,如图所示此时游标所在的行是“108”的记录,也可以在结果集上滚动游标,指向结果集中的任意一行。
2. 使用游标步骤
-
游标必须在声明处理程序之前被声明,并且变量和条件还必须在声明游标或处理程序之前被声明。
-
如果想要使用游标,一般需要经历四个步骤。不同的 DBMS 中,使用游标的语法可能略有不同。
第一步,声明游标
在MySQL中,使用DECLARE
关键字来声明游标,其语法的基本形式如下:
DECLARE cursor_name CURSOR FOR select_statement;
这个语法适用于 MySQL,SQL Server,DB2 和 MariaDB。如果是用 Oracle 或者 PostgreSQL,需要写成:
DECLARE cursor_name CURSOR IS select_statement;
要使用 SELECT
语句来获取数据结果集,而此时还没有开始遍历数据,这里 select_statement
代表的是 SELECT
语句,返回一个用于创建游标的结果集。
比如:
DECLARE cur_emp CURSOR FOR
SELECT employee_id,salary FROM employees;
DECLARE cursor_fruit CURSOR FOR
SELECT f_name, f_price FROM fruits ;
第二步,打开游标
打开游标的语法如下:
OPEN cursor_name
当我们定义好游标之后,如果想要使用游标,必须先打开游标。打开游标的时候 SELECT
语句的查询结果集就会送到游标工作区,为后面游标的逐条读取
结果集中的记录做准备。
OPEN cur_emp;
第三步,使用游标(从游标中取得数据)
语法如下:
FETCH cursor_name INTO var_name [, var_name] ...
这句的作用是使用 cursor_name
这个游标来读取当前行,并且将数据保存到 var_name
这个变量中,游标指针指到下一行。如果游标读取的数据行有多个列名,则在 INTO
关键字后面赋值给多个变量名即可。
注意:var_name
必须在声明游标之前就定义好。
FETCH cur_emp INTO emp_id, emp_sal ;
注意:游标的查询结果集中的字段数,必须跟 INTO 后面的变量数一致,否则,在存储过程执行的时候,MySQL 会提示错误。
第四步,关闭游标
CLOSE cursor_name
有 OPEN
就会有 CLOSE
,也就是打开和关闭游标。当使用完游标后需要关闭掉该游标。因为游标会占用系统资源
,如果不及时关闭,游标会一直保持到存储过程结束,影响系统运行的效率。而关闭游标的操作,会释放游标占用的系统资源。
关闭游标之后,就不能再检索查询结果中的数据行,如果需要检索只能再次打开游标。
CLOSE cur_emp;
3. 举例
- 创建存储过程“
get_count_by_limit_total_salary()
”,声明IN
参数limit_total_salary
,DOUBLE类型;声明OUT
参数total_count
,INT
类型。函数的功能可以实现累加薪资最高的几个员工的薪资值,直到薪资总和达到limit_total_salary
参数的值,返回累加的人数给total_count
。
DELIMITER //
CREATE PROCEDURE get_count_by_limit_total_salary(IN limit_total_salary DOUBLE,OUT total_count INT)
BEGIN
DECLARE sum_salary DOUBLE DEFAULT 0; #记录累加的总工资
DECLARE cursor_salary DOUBLE DEFAULT 0; #记录某一个工资值
DECLARE emp_count INT DEFAULT 0; #记录循环个数
#定义游标
DECLARE emp_cursor CURSOR FOR SELECT salary FROM employees ORDER BY salary DESC;
#打开游标
OPEN emp_cursor;
REPEAT
#使用游标(从游标中获取数据)
FETCH emp_cursor INTO cursor_salary;
SET sum_salary = sum_salary + cursor_salary;
SET emp_count = emp_count + 1;
UNTIL sum_salary >= limit_total_salary
END REPEAT;
SET total_count = emp_count;
#关闭游标
CLOSE emp_cursor;
END //
DELIMITER ;
- 查询 取多少个人的工资上线超过20w
#调用
CALL get_count_by_limit_total_salary(200000,@total_count);
SELECT @total_count;
4. 小结
-
游标是 MySQL 的一个重要的功能,为
逐条读取
结果集中的数据,提供了完美的解决方案。跟在应用层面实现相同的功能相比,游标可以在存储程序中使用,效率高,程序也更加简洁。 -
但同时也会带来一些性能问题,比如在使用游标的过程中,会对数据行进行
加锁
,这样在业务并发量大的时候,不仅会影响业务之间的效率,还会消耗系统资源
,造成内存不足,这是因为游标是在内存中进行的处理。 -
建议:用完之后就关闭的习惯,这样才能提高系统的整体效率。
更多推荐
所有评论(0)