更新时间:2025-09-19 GMT+08:00
分享

游标(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

相关文档