游标(Cursor)
简介
游标(Cursor)用于处理SQL影响的结果集,允许逐行地访问和操作这些结果集。它是指向查询结果集的一个指针,可以对每一行数据进行单独的处理。游标主要分为显示游标和隐式游标。
游标的属性
%FOUND:用于测试对游标进行FETCH的操作是否检索到行,如果FETCH检索到行,则返回TRUE。
%NOTFOUND:与%FOUND相反,如果FETCH操作没有检索到行,则返回TRUE。
%ISOPEN:用于判断游标是否打开。
%ROWCOUND:用于返回游标影响的行数。
显式游标
显式游标是用户显式定义和控制的游标,用于处理返回多行数据的SELECT查询。用户需要显示地在PL/SQL中有显式的定义游标、打开游标、使用游标和关闭游标等步骤。
隐式游标
隐式游标是数据库系统自动管理的游标。当执行SQL语句时,数据库会自动创建一个隐式游标来处理这些操作。
- 简洁性:无需显式定义和控制游标,减少了编程工作。
- 性能:由于是数据库系统自动管理,通常具有较好的性能。
- 缺乏灵活性:用户无法自定义游标的属性和行为。
示例
- 显式游标
--前置操作,建表和插入数据。 gaussdb=# CREATE TABLE tb_t1(c1 int,c2 int); NOTICE: The 'DISTRIBUTE BY' clause is not specified. Using 'c1' as the distribution column by default. HINT: Please use 'DISTRIBUTE BY' clause to specify suitable data distribution column. CREATE TABLE gaussdb=# INSERT INTO tb_t1 VALUES (generate_series(1,10),generate_series(1,10)); INSERT 0 10 --显式游标示例。 gaussdb=# DECLARE v_c1 int; v_c2 int; v_res int; --定义游标。 CURSOR v_cur IS SELECT * FROM tb_t1; BEGIN --打开游标。 OPEN v_cur; LOOP --使用游标。 FETCH v_cur INTO v_c1,v_c2; EXIT WHEN v_cur %notfound; v_res = mod(v_c1,2); IF v_res = 1 THEN UPDATE tb_t1 SET c2 = v_c1+1 WHERE c1 = v_c1; END IF; END LOOP; --关闭游标。 CLOSE v_cur; END; / ANONYMOUS BLOCK EXECUTE --查看表结果。 gaussdb=# SELECT * FROM tb_t1; c1 | c2 ----+---- 1 | 2 2 | 2 3 | 4 4 | 4 5 | 6 6 | 6 7 | 8 8 | 8 9 | 10 10 | 10 (10 rows) --删除表。 gaussdb=# DROP TABLE tb_t1; DROP TABLE
- 隐式游标
--前置操作,创建表。 gaussdb=# CREATE TABLE tb_t1(c1 int,c2 int); NOTICE: The 'DISTRIBUTE BY' clause is not specified. Using 'c1' as the distribution column by default. HINT: Please use 'DISTRIBUTE BY' clause to specify suitable data distribution column. CREATE TABLE gaussdb=# CREATE TABLE tb_t2(c1 int,c2 int); NOTICE: The 'DISTRIBUTE BY' clause is not specified. Using 'c1' as the distribution column by default. HINT: Please use 'DISTRIBUTE BY' clause to specify suitable data distribution column. CREATE TABLE --隐式游标使用。 gaussdb=# BEGIN INSERT INTO tb_t1 VALUES (generate_series(1,4),generate_series(1,4)); RAISE INFO '向tb_t1表中插入了%条数据',SQL%ROWCOUNT; INSERT INTO tb_t2 VALUES (generate_series(1,6),generate_series(1,6)); RAISE INFO '向tb_t2表中插入了%条数据',SQL%ROWCOUNT; UPDATE tb_t1 SET c2 = c2*2 WHERE c1 > 4; RAISE INFO '表tb_t1中修改了数据%条',SQL%ROWCOUNT; UPDATE tb_t2 SET c2 = c1*2 WHERE c1 > 4; RAISE INFO '表tb_t2修改了数据%条',SQL%ROWCOUNT; END; / INFO: 向tb_t1表中插入了4条数据 INFO: 向tb_t2表中插入了6条数据 INFO: 表tb_t1中修改了数据0条 INFO: 表tb_t2修改了数据2条 ANONYMOUS BLOCK EXECUTE --查看表tb_t1,tb_t2的数据。 gaussdb=# SELECT * FROM tb_t1 ORDER BY 1; c1 | c2 ----+---- 1 | 1 2 | 2 3 | 3 4 | 4 (4 rows) gaussdb=# SELECT * FROM tb_t2 ORDER BY 1; c1 | c2 ----+---- 1 | 1 2 | 2 3 | 3 4 | 4 5 | 10 6 | 12 (6 rows) --删除表。 gaussdb=# DROP TABLE tb_t1; DROP TABLE gaussdb=# DROP TABLE tb_t2; DROP TABLE