oracle 游标杂耍

/*
set serveroutput on
declare
    v_code test_user.t_test1.code%type;
    v_name  test_user.t_test1.name%type;
  
    cursor c_test is
    select code,name from test_user.t_test1;
    begin
        open c_test;
        loop
            fetch c_test into v_code,v_name;
            dbms_output.put_line(v_code ||'---------'|| v_name);
            exit when c_test%notfound;
        end loop;
                    commit;
        close c_test;
     end;
*/    
     --set serveroutput on
  /*
     declare vv_code  TEST_USER.T_TEST1.CODE%type;
                vv_name test_user.t_test1.name%type;
      v_rowcount int;
               
        cursor c_tt is select code,name from test_user.t_test1;
        begin
            if  c_tt%isopen then
                NULL;
              ELSE
            open c_tt;
            END IF;
            fetch c_tt into vv_code,vv_name;

            while c_tt%found
            loop
                if vv_code is not null then
                    if vv_name is not null then
                        insert into test_user.ta values (1,'test1111111',vv_code,vv_name,v_rowcount);
                    end if;
                end if;
                           v_rowcount:=c_tt%rowcount;-----c_tt%rowcount 游标检索出的总数据行数
            if c_tt%rowcount>3 then
                dbms_output.put_line(v_rowcount);
            end if;
                fetch c_tt into vv_code,vv_name;
    
            end loop;
                        commit;
            IF c_tt%isopen then
            close c_tt;
            else
            null;
            end if;
           
        end;
  */    
  /*
   ----游标的FOR循环  不用显示打开游标,关闭游标,测试数据的存在和定义存放数据的变量

     declare   
   Cursor c_t is select code,name from test_user.t_test1;
   begin
        for row_count in c_t
        loop
            if row_count.code is not null then
                if row_count.name is not null then
                    insert into test_user.ta values(23,'萨法款到即发',row_count.code,row_count.name,12345);
                end if;
             end if;
        end loop;
           commit;
   end;
 
 -- 替换方案
 
  begin
    for row_count in (select code,name from test_user.t_test1) loop
        insert into test_user.ta values(55,'阿司法局离开',row_count.code,row_count.name,98);
    end loop;
    commit;
  end;
  */
  /*
  ---游标FOR循环中,可以传递参数给游标
  set serveroutput on
  declare
    cursor c_ref_vai (v_id integer) is select id,code,name from test_user.ta where id=v_id;
    begin
        for row_foreach in c_ref_vai(55) loop
            dbms_output.put_line(row_foreach.id||'----'||row_foreach.code ||'----'||row_foreach.name);
        end loop;
    end;
   
    */
   
   
  ---游标变量和游标的是不同的,它们类似 变量和常量之间的关系。游标是静态的,游标变量是动态的,
  --游标变量并不与特定的查询绑定在一起。游标变量类似指针,保存某个项目的内存位置,而不是项目本身。
  --游标变量具有REF CURSOR数据类型。游标总是指向相同的查询工作区,而游标变量 能够指向不同的工作区,
  --因此游标和游标变量不能互操作。
  -----定义 REF CURSOR类型。创建游标变量:
  TYPE  ref_type_name is  REF CURSOR [RETURN  return_type];
  参数:
  return_type:必须表示一个记录或者是数据库表的一行。
  如果 显示声明: RETURN return_type 则表示 REF CURSOR 是一个强类型,否则就是一个弱类型。
  --声明游标变量
  DECLARE
    TYPE ref_type_name is  REF CURSOR  return t_goods%rowtype;
    v_ref_type_name         ref_type_name;
  或:用%type 提供记录变量店数据类型
  DECLARE
        one_record  t_goods%rowtype;
        TYPE ref_type_name is ref cursor return one_record%type;
        v_ref_type_name         ref_type_name;
       
       
   --用 用户自定义的记录类型作为返回值
   DECLARE
            TYPE myrecord is record(code varchar2(32),name varchar2(32),address varchar2(64));
            TYPE ref_type_name is ref cursor return myrecord;
            v_ref_type_name         ref_type_name;
           
    ---声明游标变量作为函数或存储过程的参数
    declare
        type ref_type_name is ref cursor return t_goods%rowtype;
        procedure open_t_goods_data(row_record in out ref_type_name)  ----必须用 IN OUT 类型
        as
        begin
        .....
        end open_t_goods_data;
               
  案例:
    create package t_goods_cv
    as
    type ref_cur_strong is ref cursor return t_goods%rowtype;
    type ref_cur_weak  is ref cursor;
    procedure my_prc(v_ref1 in out ref_cur_strong,v_ref2 in out ref_cur_weak,v_id in integer);
    end t_goods_cv;
    create package body t_goods_cv
    as
    begin
        procedure my_prc(v_ref1 in out ref_cur_strong,v_ref2 in out ref_cur_weak v_id in integer)
        is
        begin
            if v_id=1 then
                open v_ref1 for select * from test_user.t_goods;
                fetch v_ref1 into row_foreach
                loop
                    dbms_output.put_line(row_foreach.name||row_foreach.address);
                    exit when v_ref1%notfound;
                end loop;
                close v_ref1;
                else v_id<0 then
                open v_ref2 for select * from test_user.t_test1;
                fetch v_ref2 into row_foreach2
                while row_foreach2.name is not null
                loop
                    ......;
                end loop;
            end if;
        end;
    end t_goods_cv;
   
   
    ---使用 BULK COLLECT子句,从游标变量中提取多行,放入一个或多个集合中。
    DECLARE
        TYPE c_cur is ref cursor return t_goods%rowtype
        type t_name is table of t_goods.name%type;
        type t_code is table of t_goods.code%type;
        v_ref_cur   c_cur;
        v_name      t_name;
        v_code        t_code;
        begin
            open v_ref_cur for select code,name from test_user.t_goods;
            fetch v_ref_cur bulk collect into v_code,v_name;
            ...........
            close v_ref_cur;
        end;
       
    ---主变量或游标变量 格式是:变量或游标变量前加:这是在pl/sql中用法
    即 :v_i---代表主变量
        :ref_cur----代表主游标变量
       
       
  -----游标表达式
    一个游标表达式返回一个嵌套游标,结果集中的每行都包含值加上子查询生成的游标。
    游标表达式的查询,是作为游标声明的一部分,可以在动态SQL查询中使用游标表达式。语法:
    CURSOR (subquery);
   
    案例
    create or replace procedure my_test(id in integer)
    as
    type refcursor is ref cursor;
    cursor c1 is
    select a.code,
    cursor(select b.name,
    cursor(select c.name from tc c where c.id=b.ref_id)as cname
    from tb b where b.ref_ta_id=a.id)as bname
    from ta a where a.id=id;
    v_1 refcursor;
    v_2 refcursor;
    v_3 refcursor;
    v_1name ta.code%type;
    v_2name tb.name%type;
    v_3name tc.name%type;
    begin
        open c1;
        loop
        fetch c1 into v_1name,v_1;
        ....;
        exit when c1%notfound;
        loop
        fetch v_1 into v_2name,v2;
        ...;
        exit when v_1%notfound;
        loop
        fetch v2 into v_3name;
        ...;
        exit when v2%notfound;
        ....;
        end loop;
        end loop;
        end loop;
        close c1;
       
    end;
    end my_test;

你可能感兴趣的:(oracle 游标杂耍)