游标的使用

一、简介

1、游标的概念

游标(Cursor) 就是一个变动的光标,它本质上是一个指针,指向从数据库查询出来的结果集任何一条记录,初始的时候指向第一条记录。

2、游标的分类

Oracle中游标分为两类:普通游标、REF游标,普通游标又可以分为两种类型:显式游标、隐式游标.

二、显式游标

显式游标是指在使用前必须有着明确的游标声明和定义,显式游标的定义会关联查询语句,返回一条或多条记录,显示游标的使用由开发人员控制。

1、使用步骤

1)、声明游标

CURSOR cursor_name                  --声明游标,cursor_name是游标名称
    is select_statement;            --游标关联的select语句,注意:不能是select ... into 语句

2)、打开游标
游标中想要读取数据都是建立在游标已打开的前提下

OPEN cursor_name;

3)、读取数据
读取数据是使用 FETCH语句,它可以把游标指向的行记录数据提取出来赋值给声明的变量,注意:FETCH语句只能取出当前行的记录,一般情况下, FETCH语句 都是搭配 循环语句 一起使用,直到某个条件不符合退出循环.

FETCH cursor_name INTO v_name;

4)、关闭游标

CLOSE cursor_name;

2、示例

示例1:
declare 
  CURSOR cur_product                                --1、声明游标
        is select * from product;              
  v_row_product      product%rowtype;               --声明product表的行变量     
 
begin
  OPEN cur_product;                                 --2、打开游标
       LOOP
          FETCH cur_product INTO v_row_product;     --3、读取数据放入行变量
       EXIT  WHEN cur_product%NOTFOUND;
          DBMS_OUTPUT.PUT_LINE('商品名:'    ||  v_row_product.name  ||  '价格:' ||   v_row_product.price);
       END LOOP;
  CLOSE cur_product;                                --4、关闭游标  
end;


示例2:
declare 
  CURSOR cur_product
        is select name, price from product;
  v_name     product.name%type;
  v_price    product.price%type;
 
begin
  OPEN cur_product;
       LOOP
          FETCH cur_product INTO v_name, v_price;
       EXIT  WHEN cur_product%NOTFOUND;
          DBMS_OUTPUT.PUT_LINE('商品名:'    ||  v_name  ||  '价格:' ||   v_price);
       END LOOP;
  CLOSE cur_product;
end;

3、显示游标的属性

显示游标的属性用于返回其执行信息,包括:
1)ISOPEN:获取游标是否打开,已打开返回true,没有打开返回false

IF cur_product%ISOPEN  THEN
    ...                            --游标已打开执行的语句
ELSE 
  OPEN cur_product;                --游标未打开则打开游标
END IF;

2)FOUND:检查是否从结果集中提取到了数据,提取到返回true,否则返回false

LOOP
    FETCH cur_product INTO v_name, v_price;
    IF cur_product%FOUND;
        DBMS_OUTPUT.PUT_LINE('商品名:'    ||  v_name  ||  '价格:' ||   v_price);
    ELSE
        EXIT;
    END IF;
END LOOP;

3)NOTFOUND:和FOUND相反,提取到数据返回false,未提取到数据返回true
4)ROWCOUNT:返回当前已经提取了多少行数据

4、使用 FETCH ... BULK COLLECT INTO 语句提取全部数据

declare 
  CURSOR cur_product 
         is select * from product;
 
  TYPE product_tab_type IS TABLE OF product%rowtype;
  product_tab  product_tab_type;

begin
  OPEN cur_product;
      FETCH cur_product BULK COLLECT INTO product_tab;       --将数据全部提取出来放入product_tab
      FOR i in 1..product_tab.count LOOP                     --循环遍历product_tab
           DBMS_OUTPUT.PUT_LINE('商品名:'    ||  product_tab(i).name  ||  '价格:' ||   product_tab(i).price);
      END LOOP;
  CLOSE cur_product;
  
end;

5、使用 FETCH ... BULK COLLECT INTO LIMIT语句提取部分数据

declare 
  CURSOR cur_product 
         is select * from product;
 
  TYPE product_tab_type IS TABLE OF product%rowtype;
  product_tab  product_tab_type;

begin
  OPEN cur_product;
       LOOP                                          --循环1:每次提取3行数据放入product_tab
           FETCH cur_product BULK COLLECT INTO product_tab LIMIT 3;
           FOR i in 1..product_tab.count LOOP        --循环2:遍历输出product_tab中的3行数据
               DBMS_OUTPUT.PUT_LINE('商品名:'    ||  product_tab(i).name  ||  '价格:' ||   product_tab(i).price);
           END LOOP;
               DBMS_OUTPUT.PUT_LINE('-------');
       EXIT WHEN cur_product%NOTFOUND;
       END LOOP;
  CLOSE cur_product;
  
end;

6、游标FOR循环

游标的使用大部分是为了迭代结果集,在PL/SQL中有一种更方便的循环游标的方式实现

declare 
  CURSOR cur_product 
         is select * from product;
 
begin
  FOR cur_info in cur_product      --将游标返回的数据放入cur_info ,该变量是%rowtype类型,并且无需声明
  LOOP
      DBMS_OUTPUT.PUT_LINE('商品名:'    ||  cur_info.name  ||  '价格:' ||  cur_info.price);
  END LOOP;
end;

这种方式简化了对游标的处理,使用这种情况时,Oracle会隐式地打开游标、提取数据、关闭游标.

7、带参数的游标

使用显示游标时可以指定参数,参数可以传递给游标在查询语句中使用.

参数游标的定义:
    cursor cursor_name              
        (param_name datatype, ...)
        is select_statement;        

示例:

declare 
  v_cid  product.cid%type := '1';  

  CURSOR cur_product
         (param_id varchar2)           --指定参数
         is select * from product where cid = param_id;    --使用参数
  
  v_row_product    product%rowtype; 

begin
  OPEN cur_product(v_cid);            --打开游标时传入参数
  LOOP
      FETCH cur_product INTO v_row_product;
      EXIT WHEN cur_product%NOTFOUND;
      DBMS_OUTPUT.PUT_LINE(v_row_product.name);
  END LOOP;
  CLOSE cur_product;
end;

三、隐式游标

1、隐式游标的特点

隐式游标是PL/SQL自动管理的,有以下特点:
1)隐式游标有默认名称:SQL
2)每当运行SELECT语句或者DML语句时,PL/SQL会打开一个隐式游标
3)隐式游标属性值始终是最新执行的SQL语句的

declare 
  v_name  product.name%type;  

begin
  select p.name into v_name from product p where p.pid = '1';
  IF SQL%FOUND THEN
     DBMS_OUTPUT.PUT_LINE('pid为666的商品名称为:' || v_name);
  END IF;
end;

2、隐式游标的属性

隐式游标属性名称和显式游标一样,不过其含义有区别
1)ISOPEN:由Oracle控制,永远返回false
2)FOUND:反应DML语句是否影响了数据,有影响时返回true,否则返回false;也可以反应SELECT INTO语句是否返回了数据,返回了数据则该属性值为true
3)NOTFOUND:和FOUND相反,DML语句没有影响数据或SELECT INTO语句没有返回数据时值为true,其它false
4)ROWCOUNT:反应DML语句影响数据的数量

四、REF游标

REF CURSOR是一个游标变量,当使用显式游标时,必须在定义部分指定其对应的select语句,而使用REF CURSOR时,可以在打开游标时指定其对应的select语句.

1、使用步骤

1)、定义REF CURSOR类型、游标变量

TYPE ref_type IS REF CURSOR [RETURN return_type];      --定义REF CURSOR类型
cur_name    type_type;                                 --声明游标变量

2)、打开游标

OPEN cur_name FOR select_statement;

3)、提取数据:和显式游标使用方法一样
4)、关闭游标:和显式游标使用方法一样

2、示例

declare 
  v_name  product.name%type;  

  TYPE ref_type IS REF CURSOR;
  cur_product ref_type;
  
begin
  OPEN cur_product FOR select p.name from product p;
  LOOP
       FETCH cur_product INTO v_name;
       EXIT WHEN cur_product%NOTFOUND;
       DBMS_OUTPUT.PUT_LINE(v_name);
  END LOOP;
  CLOSE cur_product;
end;

3、指定RETURN子句

如果在定义REF CURSOR类型时指定了RETURN 子句,那么在select_statement中返回的结果必须与RETURN 子句定义的记录类型匹配.

declare 
  v_row_product  product%rowtype;  

  TYPE ref_type IS REF CURSOR RETURN product%rowtype;
  cur_product ref_type;
  
begin
  OPEN cur_product FOR select * from product p;      --必须是product%rowtype类型
  LOOP
       FETCH cur_product INTO v_row_product;
       EXIT WHEN cur_product%NOTFOUND;
       DBMS_OUTPUT.PUT_LINE(v_row_product.name);
  END LOOP;
  CLOSE cur_product;
end;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容

  • 1.1 基本结构 PL/SQL程序由三个块组成,即声明部分、执行部分、异常处理部分。 1.2 命名规则 1.3 记...
    慢清尘阅读 3,813评论 3 14
  • oracle存储过程常用技巧 我们在进行pl/sql编程时打交道最多的就是存储过程了。存储过程的结构是非常的简单的...
    dertch阅读 3,471评论 1 12
  • 游标概念 由select语句返回的结果集包括满足该语句的where子句中条件的所有行。但是有时候应用程序并不总能将...
    不知名的蛋挞阅读 1,958评论 0 6
  • 很多人随着年龄的增长,除却自己经常联系的朋友和家人,很少再会和其它人保持联系,长此以往养成了一个不太好的习惯...
    熙熙Breathe阅读 311评论 0 2
  • 我们的夏天,正好酝酿着一场雨。 你的自行车后座和我手中的冰棍,成了一道风景。 窗外,你穿着球衣的身影,映着夕阳的余...
    岐途和歧途阅读 156评论 0 1