
# CURSOR
#### 功能描述
CURSOR语句定义游标，用于从查询里面检索出指定的几行数据。
为了处理SQL语句，存储过程进程分配一段内存区域来保存上下文联系。游标是指向上下文区域的句柄或指针。借助游标，存储过程可以控制上下文区域的变化。
#### 注意事项
- 游标命令只能在事务块里使用。
- 通常游标和SELECT一样返回文本格式。因为数据在系统内部是用二进制格式存储的，系统必须对数据做一定转换以生成文本格式。一旦数据是以文本形式返回，客户端应用需要把它们转换成二进制进行操作。使用FETCH语句，游标可以返回文本或二进制格式。
- 应该谨慎使用二进制游标。文本格式一般都比对应的二进制格式占用的存储空间大。二进制游标返回内部二进制形态的数据，可能更易于操作。如果想以文本方式显示数据，则以文本方式检索会为用户节约很多客户端的工作。比如，如果查询从某个整数列返回1，在缺省的游标里将获得一个字符串1，但在二进制游标里将得到一个4字节的包含该数值内部形式的数值（大端顺序）。
 
#### 语法格式
```
CURSOR cursor_name
    [ BINARY ]  [ NO SCROLL ]  [ { WITH | WITHOUT } HOLD ]
    FOR query ;
```
#### 参数说明
表1CURSOR参数说明 
| 参数                        | 描述                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | 取值范围                                                                                                                                    |
|:---|:---|:---|
| cursor_name               | 要创建的游标名。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               | 字符串，需符合[标识符命名规范](https://support.huaweicloud.com/sqlreference-dws/dws_06_0007.html#ZH-CN_TOPIC_0000001811634529__section1475018612353)。 |
| BINARY                    | 指明游标以二进制而不是文本格式返回数据。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   | -                                                                                                                                       |
| NO SCROLL                 | 声明游标检索数据行的方式。 - NO SCROLL：声明该游标不能用于以倒序的方式检索数据行。  - 未声明：根据执行计划的不同，自动判断该游标是否可以用于以倒序的方式检索数据行。                                                                                        | -                                                                                                                                       |
| WITH HOLD \| WITHOUT HOLD | 声明当创建游标的事务结束后，游标是否能继续使用。 - WITH HOLD：声明该游标在创建它的事务结束后仍可继续使用。  - WITHOUT HOLD：声明该游标在创建它的事务之外不能再继续使用，此游标将在事务结束时被自动关闭。（默认行为）   | -                                                                                                                                       |
| query                     | 使用SELECT或VALUES子句指定游标返回的行。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             | SELECT或VALUES子句。                                                                                                                        |
   
#### 示例
准备表数据。
```
DROP TABLE IF EXISTS customer_address;
CREATE TABLE customer_address 
(ca_address_sk INT, 
ca_address_id VARCHAR(16), 
ca_street_number VARCHAR(10), 
ca_street_name VARCHAR(60), 
ca_street_type VARCHAR(15), 
ca_suite_number VARCHAR(10));
INSERT INTO customer_address VALUES 
(1, 'ID1', '100', 'Main', 'St', 'A1'), 
(2, 'ID2', '200', 'Oak', 'Ave', 'B2'),
(3, 'ID3', '300', 'Pine', 'Blvd', 'C3');
```
开启事务。
```
START TRANSACTION;
```
创建名称为cursor1的游标。
```
CURSOR cursor1 FOR SELECT * FROM customer_address ORDER BY 1;
```
创建名称为cursor2的游标。
```
CURSOR cursor2 FOR VALUES(1,2),(0,3) ORDER BY 1;
```
WITH HOLD游标的使用：
1. 创建一个with hold游标。
   ```
   DECLARE cursor3 CURSOR WITH HOLD FOR SELECT * FROM customer_address ORDER BY 1;
   ```
   
2. 抓取头2行到游标cursor3中。
   ```
   FETCH FORWARD 2 FROM cursor3;
   ```
   ![](https://support.huaweicloud.com/sqlreference-dws/figure/zh-cn_image_0000002660734375.png "点击放大")
   
3. 结束事务：
   ```
   END;
   ```
   
4. 抓取下一行到游标cursor3中。
   ```
   FETCH FORWARD 1 FROM cursor3;
   ```
   ![](https://support.huaweicloud.com/sqlreference-dws/figure/zh-cn_image_0000002630495202.png "点击放大")
   
5. 关闭游标。
   ```
   CLOSE cursor3;
   ```
   
 
#### 相关链接
[FETCH](https://support.huaweicloud.com/sqlreference-dws/dws_06_0216.html)
