oracle游标

 游标(cursor )是一个私有的SQL工作区域,是一个指向上下文区的句柄或指针,位于内存中的 "临时表"

 游标是SQL的一个内存工作区,由系统或用户以变量的形式定义。游标的作用就是用于临时存储从数据库中提取的数据块。在某些情况下,需要把数据从存放在磁盘的表中调到计算机内存中进行处理,最后将处理结果显示出来或最终写回数据库。这样数据处理的速度才会提高,否则频繁的磁盘数据交换会降低效率

游标用来管理从数据源返回的数据的属性(结果集)。这些属性包括并发管理、在结果集中的位置、返回的行数,以及是否能够在结果集中向前和/或向后移动(可滚动性)。

游标跟踪结果集中的位置,并允许对结果集逐行执行多个操作,在这个过程中可能返回至原始表,也可能不返回至原始表

 

原理游标是从数据表中提取出来的数据,以 临时表 的形式存放到 内存中,在游标中有一个 数据指针, 在初始状态下指向的是首记录,利用 fetch 语句可以移动该指针,从而对游标中的数据进行各种操作,然后将操作结果写回到数据库中。
作用

1、用来查询数据库,获取记录集合(结果集)的指针,可以让开发者基于当前的结果集位置检索一行或连续的几行在每     条结果集上作操作,以编 程的方式访问数据。
2、用 ‘牺牲内存’ 来提升 SQL 执行效率,适用于 大数据处理

3.在结果集的当前位置修改行中的数据,对其他用户所做的数据更改定义不同的敏感性级别。

 

程序语言是面向记录的,一组变量一次只能存放一个变量或者一条记录,无法直接接收数据库中的查询结果集引入游标就解决了这个问题

标的类型

REF 游标用于处理运行时才能确定的动态 SQL 查询的结果

隐式游标不易被用户和程序员察觉和意识到,实际上Oracle服务器使用隐式游标来解析和执行我们提交的SQL 语句;而显式游标是程序员在程序中显式声明的;通常我们说的游标均指显式游标

隐式

游标

在 PL/SQL 中使用 DML 和 select into时,会自动创建隐式游标,隐式游标自动声明、打开和关闭(无法手动查看),其名为 SQL,通过检查隐式游标的属性可以获得 最近执行的 DML 和 select into 语句的信息

DML操作和单行SELECT语句会使用隐式游标,它们是: 
* 插入操作:INSERT。 
* 更新操作:UPDATE。 
* 删除操作:DELETE。 
* 单行查询操作:SELECT ... INTO ...。

当系统使用一个隐式游标时,可以通过隐式游标的属性来了解操作的状态和结果,进而控制程序的流程。隐式游标可以使用名字SQL来访问,但要注意,通过SQL游标名总是只能访问前一个DML操作或单行SELECT操作的游标属性。所以通常在刚刚执行完操作之后,立即使用SQL游标名来访问属性

%FOUND语句影响了一行或多行时为 TRUE,前一个 fetch 语句是否有值,true:有,false:没有
%NOTFOUND

语句没有影响任何行时为TRUE,与上述相反,常被用于 退出循环,true:有,false:没有, null : 空。注意哦,只有 为 true 时,才退出(当 第一次 fetch 为 null 时,不会退出!)

EXIT WHEN SQL%NOTFOUND OR SQL%NOTFOUND IS NULL;

%ROWCOUNT语句影响的行数,当前成功执行的数据行数(非总记录数
%ISOPEN游标是否打开,始终为FALSE
SQL> DECLAREv_TOYID TOYS.ID%type := '&TOYID';v_TOYNAME TOYS.NAME%Type := '&TOYNAME';BEGINUPDATE TOYS SET NAME = v_TOYNAMEWHERE toyid=v_TOYID;IF SQL%NOTFOUND THENDBMS_OUTPUT.PUT_LINE('编号未找到。');ELSEDBMS_OUTPUT.PUT_LINE(‘表已更新');END IF;END;
DECLAREv_RoomData   rooms%ROWTYPE;
BEGINSELECT *INTO v_RoomData FROM rooms WHERE room_id = -1;IF SQL%NOTFOUND THEN 
/*注意,这里不执行,以上自动引发select into预定义异常*/INSERT INTO temp_table (char_col) VALUES 
('Not found!');END IF;
EXCEPTIONWHEN NO_DATA_FOUND THEN
/*注意,这是真正执行的*/INSERT INTO temp_table (char_col)VALUES ('Not found, exception handler');
END;
declare2    v_rows number;3  begin4    update emp5    set comm=10006    where deptno=30;7   v_rows:=SQL%ROWCOUNT;8   dbms_output.put_line('给部门30的' 
|| v_rows || '个雇员每人加了1000元奖金');9  end;

 

显式游标

显式游标在 PL/SQL 块的声明部分定义查询,该查询可以返回多行

1、一行一行的处理返回的数据。

2、保持当前处理行的一个跟踪,像一个指针一样指示当前的处理的记录。

3、允许程序员在PLSQL块中人为的控制游标的开启、关闭、上下移动

声明游标

划分存储区域,注意此时并没有执行Select 语句

 

CURSOR 游标名[(参数1 数据类型[,参数2 数据类型...])] 
IS SELECT语句; 
参数是可选部分,所定义的参数可以出现在SELECT语句的WHERE子句中。如果定义了参数,则必须在打开游标时传递相应的实际参数。 
SELECT语句是对表或视图的查询语句,甚至也可以是联合查询。可以带WHERE条件、ORDER BY或GROUP BY等子句,但不能使用INTO子句。在SELECT语句中可以使用在定义游标之前定义的变量。 

打开游标

执行Select 语句,获得结果集存储到游标中,此时游标指向结果集头, 而不是第一条记录

在可执行部分,按以下格式打开游标: 
OPEN 游标名[(实际参数1[,实际参数2...])]; 
打开游标时,SELECT语句的查询结果就被传送到了游标工作区。

结果集控制

移动游标取一条记录

在可执行部分,按以下格式将游标工作区中的数据取到变量中。提取操作必须在打开游标之后进行。 
FETCH 游标名 INTO 变量名1[,变量名2...]; 
或 
FETCH 游标名 INTO 记录变量; 
游标打开后有一个指针指向数据区,FETCH语句一次返回指针所指的一行数据,要返回多行需重复执行,可以使用循环语句来实现。控制循环可以通过判断游标的属性来进行。 
下面对这两种格式进行说明: 
第一种格式中的变量名是用来从游标中接收数据的变量,需要事先定义。变量的个数和类型应与SELECT语句中的字段变量的个数和类型一致。 
第二种格式一次将一行数据取到记录变量中,需要使用%ROWTYPE事先定义记录变量,这种形式使用起来比较方便,不必分别定义和使用多个变量。 
定义记录变量的方法如下: 
变量名 表名|游标名%ROWTYPE; 
其中的表必须存在,游标名也必须先定义。

关闭游标

显式游标打开后,必须显式地关闭。游标一旦关闭,游标占用的资源就被释放,游标变成无效,必须重新打开才能使用。

SQL>DECLAREmy_toy_price toys.toyprice%TYPE;				  声明游标CURSOR toy_cur ISSELECT toyprice FROM toysWHERE toyprice<250;BEGINOPEN toy_cur;  LOOPFETCH toy_cur INTO my_toy_price;EXIT WHEN toy_cur%NOTFOUND;DBMS_OUTPUT.PUT_LINE ('TOYPRICE=:玩具单价=:'||my_toy_price);END LOOP;CLOSE toy_cur;END;

带参数的

DECLAREdesig    VARCHAR2(20);emp_code VARCHAR2(5);empnm    VARCHAR2(20);CURSOR emp_cur(desigparam VARCHAR2) ISSELECT empno, ename FROM employeeWHERE designation=desig;BEGINdesig:= '&desig';OPEN emp_cur(desig);LOOPFETCH emp_cur INTO emp_code,empnm;EXIT WHEN emp_cur%NOTFOUND;DBMS_OUTPUT.PUT_LINE(emp_code||' '||empnm);END LOOP;CLOSE emp_cur;END

 允许使用游标删除或更新活动集中的行
声明游标时必须使用 SELECT … FOR UPDATE语句

所有返回集中的数据行都将处于行级(ROW-LEVEL)独占式锁定,其他对象只能查询这些数据行,

  不能进行UPDATE、DELETE或SELECT...FOR UPDATE操作。

   在多表查询中,使用OF子句来锁定特定的表,如果忽略了OF子句,那么所有表中选择的数据行都将被锁定。

   如果这些数据行已经被其他会话锁定,那么正常情况下ORACLE将等待,直到数据行解锁

SQL> SET SERVEROUTPUT ON
SQL> DECLAREnew_price NUMBER;CURSOR cur_toy ISSELECT toyprice FROM toys WHERE toyprice<100FOR UPDATE OF toyprice;
BEGINOPEN cur_toy;LOOPFETCH cur_toy INTO new_price;EXIT WHEN cur_toy%NOTFOUND;UPDATE toysSET toyprice = 1.1*new_priceWHERE CURRENT OF cur_toy;END LOOP;CLOSE cur_toy;COMMIT;
END;
declare2   cursor mycur(dept_no integer) is3   select * from dept4   where deptno>dept_no for update;5  begin6    for myreco in mycur(50) loop7     delete from dept8      where current of mycur;9    end loop;10  end;

循环游标

declare2   cursor c_dept is3   select deptno, dname from dept order by deptno;4   cursor c_emp(p_dept varchar2) is5    select ename,sal from emp where deptno=p_dept order by ename;6    v_salary emp.sal%type;7  begin8     for r_dept in c_dept loop9       dbms_output.put_line('Department:' || r_dept.deptno||'-'||r_dept.dname);10     v_salary:=0;11     for r_emp in c_emp(r_dept.deptno) loop12      dbms_output.put_line('Name:'|| r_emp.ename||' salary='||r_emp.sal);13       v_salary:=v_salary+r_emp.sal;14      end loop;15      dbms_output.put_line('total salary for dept:'|| v_salary);16     end loop;17* end;

 

动态SELECT

Oracle支持动态SELECT语句和动态游标,动态的方法大大扩展了程序设计的能力。 
对于查询结果为一行的SELECT语句,可以用动态生成查询语句字符串的方法,在程序执行阶段临时地生成并执行,语法是: 
execute immediate 查询语句字符串 into 变量1[,变量2...]; 

SET SERVEROUTPUT ON   DECLARE   str varchar2(100);  v_ename varchar2(10);  begin  str:='select ename from scott.emp where empno=7788';  execute immediate str into v_ename;   dbms_output.put_line(v_ename);  END;   

 

REF

游标

在变量声明部分定义的游标是静态的,不能在程序运行过程中修改。虽然可以通过参数传递来取得不同的数据,但还是有很大的局限性。通过采用动态游标,可以在程序运行阶段随时生成一个查询语句作为游标。要使用动态游标需要先定义一个游标类型,然后声明一个游标变量,游标对应的查询语句可以在程序的执行过程中动态地说明。

 

REF 游标和游标变量用于处理运行时动态执行的 SQL 查询
创建游标变量需要两个步骤:
声明 REF 游标类型
声明 REF 游标类型的变量

TYPE <ref_cursor_name> IS REF CURSOR
[RETURN <return_type>];

声明强类型的 REF 游标

1、for 后是 SQL语句(而不能是 字符串)
2、cur… 必须和 return 的 类型完全一致
3、无法使用 绑定变量

TYPE my_curtype IS REF CURSORRETURN stud_det%ROWTYPE;
order_cur my_curtype; 

声明弱类型的 REF 游标,系统类型 SYS_REFCURSOR

TYPE my_ctype IS REF CURSOR;
stud_cur my_ctype;
declare2    type cursor_type  is ref cursor;3    stu_cursor cursor_type;4    v_stu 学生表%rowtype;5  begin6    open stu_cursor for7      select * from 学生表 where 性别='男';8    loop9      fetch  stu_cursor into v_stu;10      exit when stu_cursor%notfound;11     dbms_output.put_line(v_stu.学号 ||' '||v_stu.姓名||' '||v_stu.性别||' '||v_stu.年龄);12    end loop;13   close stu_cursor;14  end;
declare2  type emp_type is ref cursor;3  cur emp_type;4  name varchar2(20);5  salary number(7,2);6  begin7    open cur for 'select ename,sal from emp where job=:1'8    using 'SALESMAN';9   loop10     fetch cur into name,salary;11     exit when cur%notfound;12    dbms_output.put_line(name||':'||salary);13   end loop;14   close cur;15  end;
 declare2   type empcurtyp is ref cursor;3   type idlist is table of emp.empno%type;4   type namelist is table of emp.ename%type;5   type sallist is table of emp.sal%type;6   emp_cv empcurtyp;7   ids idlist;8   names namelist;  sals sallist;9   row_cn number;10  begin11    open emp_cv for select empno,ename,sal from emp;12    fetch emp_cv bulk collect into ids,names,sals;13   close emp_cv;14   for i in ids.first.. ids.last loop15     dbms_output.put_line(ids(i)||' '||names(i)||' '||sals(i));16   end loop;17* end;

 

游标变量的优点和限制

游标变量的功能强大,可以简化数据处理。
游标变量的优点有:
可从不同的 SELECT 语句中提取结果集
可以作为过程的参数进行传递
可以引用游标的所有属性
可以进行赋值运算
使用游标变量的限制:
不能在程序包中声明游标变量
FOR UPDATE子句不能与游标变量一起使用
不能使用比较运算符

DECLAREv_sql VARCHAR(2000);v_b1 NUMBER(3) := 3;TYPE record_stu IS RECORD(v_id system.stu.s_id%TYPE,v_xm system.stu.s_xm%TYPE);TYPE table_stu IS TABLE OF record_stu;v_stu table_stu;cur_stu SYS_REFCURSOR;
BEGINv_sql := 'SELECT t.s_id, t.s_xm FROM stu t WHERE t.s_id <= :b1';OPEN cur_stu FOR v_sqlUSING v_b1; -- 绑定变量 : 大数据处理常用优化手段LOOPFETCH cur_stu BULK COLLECTINTO v_stu LIMIT 1; -- 数据量太少,仅当前测试使用哦,实际开发 建议 500 左右EXIT WHEN v_stu.count = 0;FOR i IN v_stu.first .. v_stu.last LOOPdbms_output.put_line('序号:' || v_stu(i).v_id || ' , ' || '姓名:' || v_stu(i).v_xm);END LOOP;END LOOP;CLOSE cur_stu;EXCEPTIONWHEN OTHERS THENdbms_output.put_line(SQLCODE || ' : ' || SQLERRM);dbms_output.put_line(dbms_utility.format_error_backtrace);
END;

 

%type、%rowtype、record
  • %type:单条 记录类型自动匹配
  • %rowtype:所有 记录类型自动匹配
  • record:部分 记录类型自动匹配,该变量类型允许用户在代码中使用“表”,以便存储多个行数据。记录表类型是对记录类型的扩展,可以处理多个记录或多行数据
集合操作

在 Oracle 中集合中,若想扩充大小有两种方法
方式1:(手动)集合.extend(一次只申请一个空间长度)
方式2:(自动)Type <Type_name> IS TABLE OF <data_type> index by ..
Oracle 下标定义和其他语言有些区别
下标从 1 开始算,而不是 0 哦。

varry 一维数组(设置长度)

type 数组名 is varray(size) of 元素类型 [not null];

size : 数组最大长度,必填项。

DECLARE
   TYPE varry IS VARRAY(4) OF VARCHAR2(30); -- 最大长度是 4
   v_varry varry;
BEGIN
   -- 初始化 3 个下标, 也就只能写 3 个长度,即使定义的 有 4 个长度
   v_varry  := varry('a', 'b', 'c'); -- 构造方法 进行初始化

   FOR i IN v_varry.first .. v_varry.last LOOP
      dbms_output.put_line(v_varry (i));
   END LOOP;

END;
/

table 多维数组

type table_name is table of element_type[not null]
[index by [binary_integer|pls_integer]];

index by : 创建一个主键索引,以便引用记录表变量中的特定行.
-- 下列参数下标自增(无需 显示初始化:extend)
binary_integer :  由 Oracle来 执行,不会出现溢出,但是执行速度较慢,
                  因为它是由 Oracle 模拟执行。
pls_integer    :  由硬件即直接由 CPU 来运算,因而会出现溢出,但其执行速度
                  较前者快许多,数据范围:参考 ‘Oracle 官方解释中的红色字体’

 存储单行多列

(效果同 varry 一维数组)

这个和 VARRAY 类似。但是赋值方式稍微有点不同,不能使用同名的 构造函数 进行赋值。
有个细节:去掉 index by .. 后,是可以使用 构造函数

DECLARE
   -- 此例中  INDEX BY PLS_INTEGER 加不加都可以,具体解释看后面
   TYPE varry_stu IS TABLE OF VARCHAR2(30) INDEX BY PLS_INTEGER;
   v_stu_varry varry_stu;
BEGIN

   -- varry_stu := varry_stu('a', 'b', 'c'); 
   -- 此时 不能像 varry 使用上述 构造函数 进行初始化了哦

   v_stu_varry(1) := 'a';
   v_stu_varry(2) := 'b';
   v_stu_varry(3) := 'c';

   FOR i IN v_stu_varry.first .. v_stu_varry.last LOOP
      dbms_output.put_line(i || ' : ' || v_stu_varry(i));
   END LOOP;

END;
/

存储多行多列TYPE <类型名> IS TABLE OF [%rowtype / record]
若想匹配所有字段,与 %rowtype 最为方便
若想匹配部分字段,与 record 最为方便
下列实例是数据仓库中,表同步 的常见写法
当然,实现功能的写法有很多种,这里,只给出我认为最优的。
DECLAREi_stu_id NUMBER(3) := 3; -- 模拟入参 v_sql    VARCHAR(2000);cur_stu  SYS_REFCURSOR;TYPE record_stu IS RECORD(v_id   stu.id%TYPE,v_name stu.name%TYPE);TYPE table_stu IS TABLE OF record_stu; -- 思考:加不加 index by ...?v_stu table_stu;BEGINv_sql := 'SELECT t.id, t.name FROM stu t WHERE t.id <= :b1';OPEN cur_stu FOR v_sqlUSING i_stu_id; -- 绑定变量 : 大数据处理常用优化手段LOOPFETCH cur_stu BULK COLLECTINTO v_stu LIMIT 2; -- 数据量太少,仅当前测试使用哦,实际开发 建议 500 左右EXIT WHEN v_stu.count = 0;-- 细节:如果此处使用 cur_stu%notfound 不足 limit n 的数据不会在操作了哦FOR i IN v_stu.first .. v_stu.last LOOPdbms_output.put_line('学号:' || v_stu(i).v_id || ' , ' || '姓名:' || v_stu(i).v_name);-- 模拟表同步(不存在时 insert、存在时 update)END LOOP;END LOOP;CLOSE cur_stu;EXCEPTIONWHEN OTHERS THENIF cur_stu%ISOPEN THENCLOSE cur_stu;END IF;dbms_output.put_line(SQLERRM);dbms_output.put_line(dbms_utility.format_error_backtrace);
END;
/

 

何时使用 index byPL/SQL 向 集合类型 中插入数据时,必须先扩展 内存空间,有两种方式
  • 手动:extend()
  • 自动:index by …

 

DECLARETYPE string_array IS TABLE OF VARCHAR2(30);TYPE string_array_index IS TABLE OF VARCHAR2(30) INDEX BY PLS_INTEGER;v_a string_array;v_b string_array_index;
BEGIN-- 不加 INDEX BY... 是 可以 使用构造函数的v_a := string_array('a1', 'a2', 'a3');-- 加了 INDEX BY... 是 不能 使用构造函数的-- varry_stu := varry_stu('b1', 'b2', 'b3'); v_b(v_b.count) := 'b0'; -- 细节: 刚开始,数组为空,故  v_b.count = 0v_b(v_b.count) := 'b1'; -- 之后 count 依次递增(切记:不可指定 count哦,不然就不递增了,而是重复修改原记录)v_b(v_b.count) := 'b2';-- TODO: 分别插入新数据 new1, new2-- v_av_a.extend(2);v_a(4) := 'new1';v_a(5) := 'new2';FOR i IN v_a.first .. v_a.last LOOPdbms_output.put_line(i || ' : ' || v_a(i));END LOOP;dbms_output.new_line();-- v_bv_b(v_b.count) := 'new1';v_b(v_b.count) := 'new2';FOR i IN v_b.first .. v_b.last LOOPdbms_output.put_line(i || ' : ' || v_b(i));END LOOP;
END;
/1 : a1
2 : a2
3 : a3
4 : new1
5 : new20 : b0
1 : b1
2 : b2
3 : new1
4 : new2

 

空数组时
  • 没加 index by 的数组必须 初始化
  • 空数组时,array.first = array.last = null;
  • 空数组时,array.count = 0;
DECLARETYPE string_array IS TABLE OF VARCHAR2(30);TYPE string_array_index IS TABLE OF VARCHAR2(30) INDEX BY PLS_INTEGER;v_a string_array := string_array(); -- 必须先初始化v_b string_array_index; -- 加了 index by 相当于 默认初始化
BEGINdbms_output.put_line('v_a.first: ' || v_a.first);dbms_output.put_line('v_a.last: ' || v_a.last);dbms_output.put_line('v_a.count: ' || v_a.count);dbms_output.new_line();dbms_output.put_line('v_b.first: ' || v_b.first);dbms_output.put_line('v_b.last: ' || v_b.last);dbms_output.put_line('v_b.count: ' || v_a.count);
END;
/v_a.first: 
v_a.last: 
v_a.count: 0v_b.first: 
v_b.last: 
v_b.count: 0

 

清除数组元素 delete 和 置 null 的区别
  • 置 null:清除数组元素,但 不删除内存空间
  • delete:清除数组元素,并且 删除内存空间
DECLARETYPE string_array_index IS TABLE OF VARCHAR2(30) INDEX BY PLS_INTEGER;v_b string_array_index;
BEGINv_b(v_b.count) := 'b1'; -- 因为 数组为空,故而 v_b.count = 0v_b(v_b.count) := 'b2';v_b(v_b.count) := 'b3';-- TODO:置 null 方式,清除数组元素dbms_output.put_line('原数组长度:' || v_b.count);v_b(0) := NULL;dbms_output.put_line('置 null 后的长度:' || v_b.count);FOR i IN v_b.first .. v_b.last LOOPdbms_output.put_line(i || ' : ' || v_b(i));END LOOP;dbms_output.new_line();-- TODO:delete 方式,清除数组元素v_b.delete(0);dbms_output.put_line('delete 后的长度:' || v_b.count);FOR i IN v_b.first .. v_b.last LOOPdbms_output.put_line(i || ' : ' || v_b(i));END LOOP;
END;
/原数组长度:3
置 null 后的长度:3
0 : 
1 : b2
2 : b3delete 后的长度:2
1 : b2
2 : b3

 

数组遍历时,不连续下标异常

数组遍历时,是严格按照下标顺序来的,若中间出现 断层(找不到下标),就会报错

DECLARETYPE string_array_index IS TABLE OF VARCHAR2(30) INDEX BY PLS_INTEGER;v_b string_array_index;
BEGINv_b(v_b.count) := 'b1'; -- 因为 数组为空,故而 v_b.count = 0v_b(v_b.count) := 'b2';v_b(v_b.count) := 'b3';v_b.delete(1); -- 删除 'b2'FOR i IN v_b.first .. v_b.last LOOP-- 测试时,请去掉 IF,直接 dbms_output 即可。IF v_b.exists(i) THENdbms_output.put_line(i || ' : ' || v_b(i));END IF;END LOOP;
END;
/0 : b1
2 : b3

 

 

数组属性和函数属性/函数    描述
count    返回集合中元素的个数
delete    删除集合中 所有 的元素及 extend
delete(x)    删除元素下标为 x 的元素(对 varry 非法)
delete(x, y)    删除元素下标从 x 到 y 的元素(对 varry 非法)
trim    从集合末端开始删除一个元素(对 index by 非法)
trim(x)    从集合末端开始删除 x 个元素 (对 index by 非法)
exists(x)    如果集合元素 x 已经 初始化(extend) ,则返回 true,否则返回 false
extend    在集合 末尾 添加一个元素(对 index by 非法)
extend(x)    在集合 末尾 添加 x个元素 (对 index by 非法)
extend(x, n)    在集合 末尾 添加元素 x 个下标为n 的 副本(对 index by 非法)
first    返回集合中第一个元素的下标号,对 varry 集合 始终 返回 1(除非 未初始化 则为 空)
last    返回集合中最后一个元素的下标号,对 varry 集合 值始终 等于 count (除非 未初始化 则为 空)
limit    返回 varry 集合的最大的元素个数,对 index by 无效
next(x)    返回在第 x 个元素之后紧挨着它的元素下标(x+1),若 x 是最后一个元素,则返回 null
prior(x)    返回在第x个元素之前紧挨着它的 元素下标(x-1),如果 x 是第一个元素,则返回 null
Cursor与 Ref Cursor区别从技术底层看,两者是相同的。普通plsql cursor在定义时是“静态”的。而Ref cursors可以动态打开。
 
Ref cursor根据逻辑动态打开;而游标cursor定义好了就无法修改了
ref cursor可以返回给客户端,cursor则不行。
cursor可以是全局的global ,ref cursor则必须定义在过程或函数中。
ref cursor可以在子程序间传递,cursor则不行。
cursor中定义的静态sql比ref cursor效率高,所以ref cursor通常
 ①静态游标是静态定义,REF 游标是动态关联;

 ②使用REF 游标需REF 游标变量。

 ③REF 游标能做为参数进行传递,而静态游标是不可能的。

总结游标用于处理查询结果集中的数据
游标类型有:隐式游标、显式游标和 REF 游标
隐式游标由 PL/SQL 自动定义、打开和关闭
显式游标用于处理返回多行的查询
显式游标可以删除和更新活动集中的行
要处理结果集中所有记录时,可使用循环游标
在声明 REF 游标时,不需要将 SELECT 语句与 其关联 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/535497.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

系统学习SpringFramework:Spring IOC

本篇内容包括&#xff1a;IOC 和 DI 的概念、Spring 容器&#xff0c;即 BenaFactory 与 AplicationConext 等 IOC 相关内容。 一、IOC 和 DI 的概念 1、IOC IoC&#xff08;Inversion of control &#xff09;即“控制反转”&#xff0c;它是一种设计思想而非一个技术实现。…

rowid

ROWID的格式rowidOOOOOOFFFBBBBBBRRR说明数据对象号相对文件号数据块号行号 上述表格是Oracle 9i及以上版本数据库中的rowid格式: 6位对象号3位相对文件号6位数据块号3位行号&#xff0c;是一个18位的64进制值。这个18位的64进制值在数据库内却是以10个bytes合计80个bit的二进制…

系统学习SpringFramework:循环依赖与三级缓存

本篇内容包括&#xff1a;Spring 中的循环依赖问题&#xff08;包括 Spring 中的循环依赖问题和Spring 中的循环依赖的 5 种场景的介绍&#xff09;、Spring 三级缓存介绍、4 个 Spring 无法自动解决的循环以来场景以及其对应的手动解决方式。 一、Spring 中的循环依赖问题 1、…

深入理解Java虚拟机:Java类的加载机制

本篇内容包括&#xff1a;Java 类的加载机制&#xff08;Jvm 结构组成、Java 类的加载&#xff09;、类的生命周期&#xff08;加载-验证-准备-解析-初始化-使用-卸载&#xff09;、类加载器 以及 双亲委派模型。 一、Java 类的加载机制 1、 Jvm 结构组成 Jvm 整体组成可分为…

新版谷歌浏览器开启Flash支持

浏览器地址栏中输入chrome://version查看Chrome浏览器、Flash插件的版本信息。 Chrome 69.0-70.0版本Chrome 71.0-74.0及以后版本谷歌浏览器地址栏中输入【chrome://flags/#enable-ephemeral-flash-permission】&#xff0c;将【Enable Ephemeral Flash Permissions】从【Defau…

深入理解Java虚拟机:Java垃圾回收机制

本篇内容包括&#xff1a;JAVA 垃圾回收机制概述、有哪些内存需要回收、如何回收&#xff08;标记-清除、标记-整理&#xff08;标记-清除-压缩&#xff09;、复制&#xff08;标记-复制-清除&#xff09;、分代收集等算法&#xff09; 以及 何时进行垃圾回收等内容&#xff01…

深入理解Java虚拟机:Java垃圾回收器

本篇内容包括&#xff1a;7 种 Jvm 垃圾回收器的介绍、对比 以及 对应的 Jvm 参数设置&#xff0c;这 7 种包括了&#xff1a;Serial、ParNew 以及 Parallel Scavenge 三种新生代回收器 和 &#xff1a;Serial Old、Parallel Old 以及 CMS 三种老年代回收器&#xff0c;此外还有…

网络协议:什么是网络分层的七四五

本篇内容包括&#xff1a;网络分层七层、五层、四层网络协议概念的介绍&#xff0c;IOS 体系结构的介绍与构成、TCP/IP体系结构的简介及与IOS体系的关系 以及五层体系结构的介绍。 一、七层、五层、四层网络协议概念 1、关于网络协议 网络协议&#xff0c;即是指计算机网络中…

网络协议:一文搞懂Socket套接字

本篇内容包括&#xff1a;Socket 套接字的简介、Socket 套接字的分类、Java 中的 Socket 即 java.net.ServerSocket、java.net.Socket 的使用&#xff0c;以及Java 使用套接字 Scoket 编程的Demo。 一、Socket 简介 TCP&#xff08;传输控制协议&#xff09;是一种面向连接的、…

网络协议:透彻解析HTTP协议

本篇内容包括&#xff1a;HTTP 协议定义及其特点概述、关于 URL 定义及分类概述、Request 请求、Response 响应 以及 浏览器访问一个网站的全过程 等内容… 一、HTTP 协议概述 HTTP&#xff08;HyperText Transfer Protocol&#xff09; 即 超文本传输协议&#xff0c;它是一种…

Redis系列:Redis的概述与安装

Redis(Remote Dictionary Server) 是一个使用 C 语言编写的&#xff0c;开源的&#xff08;BSD许可&#xff09;高性能非关系型&#xff08;NoSQL&#xff09;的键值对数据库。 本篇内容包括&#xff1a;Redis 简介&#xff08;为什么快&#xff1f;为什么单线程&#xff1f;优…

Redis系列:Redis持久化机制与Redis事务

Redis 是个基于内存的数据库。那服务一旦宕机&#xff0c;内存中数据必将全部丢失。所以丢失数据的恢复对于 Redis 是十分重要的&#xff0c;我们首先想到是可以从数据库中恢复&#xff0c;但是在由 Redis 宕机时&#xff08;说明相关工作正在运行&#xff09;且数据量很大情况…

TCP连接的建立与终止

TCP连接的建立与终止 1.三次握手 TCP是面向连接的&#xff0c;无论哪一方向另一方发送数据之前&#xff0c;都必须先在双方之间建立一条连接。在TCP/IP协议中&#xff0c;TCP协议提供可靠的连接服务&#xff0c;连接是通过三次握手进行初始化的。三次握手的目的是同步连接双方…

13 张图带你学懂 Kubernetes Service(转载)

在 Kubernetes 中 Service 主要有4种不同的类型&#xff0c;其中的 ClusterIP 是最基础的&#xff0c;如下图所示&#xff1a; 当我们创建一个 NodePort 的 Service 时&#xff0c;它也会创建一个 ClusterIP&#xff0c;而如果你创建一个 LoadBalancer&#xff0c;它就会创建一…

DOCKERFILE参数注解

Dockerfile由一行行命令语句组成&#xff0c;并且支持以#开头的注释行。 一般的&#xff0c;Dockerfile 分为四部分&#xff1a;基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。 Dockerfile的指令是忽略大小写的&#xff0c;建议使用大写&#xff0c;使用 # 作为…

Zookeeper:分布式过程协同技术

Zookeeper 是一个高性能的分布式一致系统&#xff0c;在分布式系统中有着广泛的应用。基于它&#xff0c;可以实现诸如“分布式同步”、“配置管理”、“命名空间管理”等众多功能&#xff0c;是分布式系统中常见的基础系统。Zookeeper 主要用来解决分布式集群中应用系统的一致…

Linux namespace概述

操作系统通过虚拟内存技术&#xff0c;使得每个用户进程都认为自己拥有所有的物理内存&#xff0c;这是操作系统对内存的虚拟化。操作系统通过分时调度系统&#xff0c;每个进程都能被【公平地】调度执行&#xff0c;即每个进程都能获取到CPU&#xff0c;使得每个进程都认为自己…

Zookeeper:Zookeeper的主从选举机制

ZAB 协议&#xff0c;全称 Zookeeper Atomic Broadcast&#xff08;Zookeeper 原子广播协议&#xff09;&#xff0c;是为分布式协调服务 ZooKeeper 专门设计的一种支持崩溃恢复的一致性协议。基于该协议&#xff0c;ZooKeeper 实现了一种主从模式的系统架构来保持集群中各个副…

Linux namespace之:uts namespace

理解uts namespace uts(UNIX Time-Sharing System) namespace可隔离hostname和NIS Domain name资源&#xff0c;使得一个宿主机可拥有多个主机名或Domain Name。换句话说&#xff0c;可让不同namespace中的进程看到不同的主机名。 例如&#xff0c;使用unshare命令(较新版本L…