
# CURSOR
#### 功能描述
CURSOR命令用于创建一个游标，从一个查询里面检索出指定的几行数据。
为了处理SQL语句，存储过程线程分配一段内存区域来保存上下文联系。游标是指向上下文区域的句柄或指针。借助游标，存储过程可以控制上下文区域的变化。
#### 注意事项
- 游标命令只能在事务块里使用。
- 通常游标和SELECT一样返回文本格式。因为数据在系统内部是用二进制格式存储的，系统必须对数据做一定转换以生成文本格式。一旦数据是以文本形式返回，客户端应用需要把它们转换成二进制进行操作。使用FETCH语句，游标可以返回文本或二进制格式。
- 应该小心使用二进制游标。文本格式一般都比对应的二进制格式占用的存储空间大。二进制游标返回内部二进制形态的数据，可能更易于操作。如果想以文本方式显示数据，则以文本方式检索会为用户节约很多客户端的工作。比如，如果查询从某个整数列返回1，在缺省的游标里将获得一个字符串1，但在二进制游标里将得到一个4字节的包含该数值内部形式的数值（大端顺序）。
- 静态游标支持定义参数，参数支持默认值。但是参数默认值不能应用PACKAGE外的变量，如果需要使用，可以在包内定义一个变量，再将包外变量赋值给该变量，使用该变量作为默认值。
- 游标的定义会产生查询对象，PACKAGE或存储过程暂不支持建立对查询对象的依赖关系。
 
#### 语法格式
```
CURSOR cursor_name
    [ BINARY ]  [ NO SCROLL ]  [ { WITH | WITHOUT } HOLD ]
    FOR query;
```
![](https://support.huaweicloud.com/distributed-devg-v8-gaussdb/figure/zh-cn_image_0000002527057342.png "点击放大")
#### 参数说明
- **cursor_name**
  将要创建的游标名。
  取值范围：遵循数据库对象命名规范。
  
- **BINARY**
  指明游标以二进制而不是文本格式返回数据。
  
- **NO SCROLL**
  声明游标检索数据行的方式。
  - NO SCROLL：声明该游标不能用于以倒序的方式检索数据行。
  
  - 未声明：根据执行计划的不同，自动判断该游标是否可以用于以倒序的方式检索数据行。
   
- **WITH HOLD \| WITHOUT HOLD**
  声明当创建游标的事务结束后，游标是否能继续使用。
  - WITH HOLD：声明该游标在创建它的事务结束后仍可继续使用。
  
  - WITHOUT HOLD：声明该游标在创建它的事务之外不能再继续使用，此游标将在事务结束时被自动关闭。
  
  - 如果不指定WITH HOLD或WITHOUT HOLD，默认行为是WITHOUT HOLD。
  
  - 跨节点事务不支持WITH HOLD（例如在多Coordinator部署集群中所创建的含有DDL的事务属于跨节点事务）。
   
- **query**
  使用SELECT或VALUES子句指定游标返回的行。
  取值范围：SELECT或VALUES子句。
  
 
#### 示例
示例1：
```
--建表并插入数据。
gaussdb=# CREATE TABLE tbl_test(c1 int);
gaussdb=# INSERT INTO tbl_test VALUES (generate_series(1,20));
--建立一个名为cursor1的游标。
gaussdb=# BEGIN;
gaussdb=# CURSOR cursor1 FOR SELECT * FROM tbl_test ORDER BY 1;
--使用FETCH命令检索3行数据。
gaussdb=# FETCH FORWARD 3 FROM cursor1;
 c1 
----
  1
  2
  3
(3 rows)
--使用MOVE命令使游标向后移动2行，不返回结果。
gaussdb=# MOVE FORWARD 2 FROM cursor1;
MOVE 2
--使用FETCH命令检索两行数据。
gaussdb=# FETCH FORWARD 2 FROM cursor1;
 c1 
----
  6
  7
(2 rows)
--关闭游标并结束事务。
gaussdb=# CLOSE cursor1;
gaussdb=# END;
```
示例2：带WITH HOLD属性的游标：
```
--建立一个名为cursor2的WITH HOLD游标。
gaussdb=# BEGIN;
gaussdb=# CURSOR cursor2 WITH HOLD FOR SELECT * FROM tbl_test ORDER BY 1;
--使用FETCH命令检索3行数据。
gaussdb=# FETCH FORWARD 3 FROM cursor2;
 c1 
----
  1
  2
  3
(3 rows)
--和普通的游标不一样，结束事务后，带WITH HOLD属性的游标依然可以使用。
gaussdb=# END;
gaussdb=# FETCH FORWARD 2 FROM cursor2;
 c1 
----
  4
  5
(2 rows)
--关闭游标。
gaussdb=# CLOSE cursor2;
--删除。
gaussdb=# DROP TABLE tbl_test;
```
#### 相关链接
[FETCH](https://support.huaweicloud.com/distributed-devg-v8-gaussdb/gaussdb-12-0635.html#ZH-CN_TOPIC_0000002527826246)，[CLOSE](https://support.huaweicloud.com/distributed-devg-v8-gaussdb/gaussdb-12-0526.html#ZH-CN_TOPIC_0000002559105891)，[MOVE](https://support.huaweicloud.com/distributed-devg-v8-gaussdb/gaussdb-12-0651.html#ZH-CN_TOPIC_0000002527986200)
