Oracle——游标

版权声明:最终解释权归属Hern、HernSong(hernsong)、苍鹭、www.hernsong.com所有! https://blog.csdn.net/qq_36761831/article/details/88350770

简介

PL/SQL 是用游标来管理 SQL 的 SELECT 语句的 。游标是为了处理这些语句而分配的一大块内存。 它提供了对一个结果集进行逐行处理的能力 , 可看作是一种特殊的指针 . 它与某个查询结果集相关联 , 可以指向结果集的任意位置 , 以便对指定位置的数据进行处理 。使用它可以在查询数据的同时对数据进行处理。

游标类型

隐式游标

1、使用DML语句(增删改)和单行查询语句(赋值)时自动创建隐式游标

2、隐式游标自动声明、打开和关闭,其名为 SQL

3、通过检查隐式游标的属性可以获得最近执行的DML 语句的信息

4、隐式游标的属性:

(1)、%FOUND:SQL 语句影响了一行或多行时为 TRUE。只有在 DML 语句影响一行或多行时,才返回 True。

BEGIN
	UPDATE t_student SET sname = '张三丰'
	WHERE sid= ‘10001';

	IF  SQL%FOUND  THEN
		DBMS_OUTPUT.PUT_LINE('表已更新');
	END IF;
     END;

(2)、%NOTFOUND : SQL 语句没有影响任何行时为TRUE。如果 DML 语句不影响任何行,则返回 True。

 BEGIN
             UPDATE emp SET deptno=20 WHERE empno=7839;  
            IF SQL%NOTFOUND  THEN
                             DBMS_OUTPUT.PUT_LINE('编号未找到。');
 	ELSE
		DBMS_OUTPUT.PUT_LINE(‘数据已更新');
	END IF;
     END;

(3)、%ROWCOUNT : SQL 语句影响的行数,没有影响任何行,返回0,在执行任何DML语句前,值为NULL。

如果没有与SELECT INTO语句中的条件匹配的行,将引发NO_DATA_FOUND异常。

扫描二维码关注公众号,回复: 5481571 查看本文章
DECLARE 
	v_no  emp.empno%type;
	v_name emp.ename%type;
 BEGIN
	v_no:= &职员编号;
	SELECT ename INTO  v_name 
	FROM  emp  WHERE  empno=v_no;
     IF SQL%ROWCOUNT>0 THEN
	  DBMS_OUTPUT.PUT_LINE('职员的姓名是 '||v_name);
     END IF;
	EXCEPTION
	   WHEN NO_DATA_FOUND THEN
	     DBMS_OUTPUT.PUT_LINE('职员未找到');
 END;

(4)、%ISOPEN  : 游标是否打开,隐式游标始终为FALSE(隐式游标执行时打开,结束时立即关闭)

显示游标

1、显式游标是由PL/SQL程序员定义和命名的游标

2、显式游标用于多行查询

3、显式游标需要在PL/SQL块的声明部分声明,在执行部分或异常处理部分打开,取完数据后将其关闭

声明游标

CURSOR  cursor_name  IS  select_statement;

打开游标(将数据存储到游标)

OPEN  cursor_name;

根据游标提取数据

FETCH  cursor_name  INTO variable[,variable,……]

关闭游标

CLOSE  cursor_name;

使用游标循环打印所有学生姓名

Declare
  v_name t_student.sname%type;
  Cursor cur_stu Is select  sname  from t_student; --声明游标
begin
  Open cur_stu; --打开游标
  Loop
    Fetch cur_stu Into  v_name;  --提取游标指向数据给变量
    Exit When cur_stu%NotFound;
    dbms_output.put_line('学生姓名:'||v_name); 
  End Loop;
  Close cur_stu;  --关闭游标
end;

使用游标循环打印所有员工编号,员工姓名及工资

declare
  CURSOR c_emp IS
    SELECT empno,ename,sal FROM emp ORDER BY sal;
  v_empno emp.empno%TYPE;
  v_ename emp.ename%TYPE;
  v_sal emp.sal%TYPE;
begin
  Open c_emp;
  Loop
    Fetch c_emp Into  v_empno,v_ename,v_sal;
    Exit When c_emp%NotFound;
    dbms_output.put_line(v_empno||’  ’||v_ename||’  ’||v_sal); 
  End Loop;
  Close c_emp;
end;

使用游标循环打印所有员工编号,员工姓名及工资

declare
  CURSOR c_emp IS
    SELECT empno,ename,sal FROM emp ORDER BY sal;
  v_empno emp.empno%TYPE;
  v_ename emp.ename%TYPE;
  v_sal emp.sal%TYPE;
begin
  Open c_emp;
  Loop
    Fetch c_emp Into  v_empno,v_ename,v_sal;
    Exit When c_emp%NotFound;
    dbms_output.put_line(v_empno||’  ’||v_ename||’  ’||v_sal); 
  End Loop;
  Close c_emp;
end;

使用游标行循环打印员工编号,姓名,工资

declare
  CURSOR c_emp IS
    SELECT empno,ename,sal FROM emp ORDER BY sal; 
    r_emp c_emp%ROWTYPE;--游标行
begin
  Open c_emp;
  Loop
    Fetch c_emp Into r_emp;
    Exit When c_emp%NotFound;
dbms_output.put_line(r_emp.empno||’  ’||r_emp.ename||’  ’||r_emp.sal);
  End Loop;
  Close c_emp;
end;

使用游标行循环打印员工编号,姓名,工资

declare
  CURSOR c_emp IS
    SELECT empno,ename,sal FROM emp ORDER BY sal; 
    r_emp c_emp%ROWTYPE;--游标行
begin
  Open c_emp;
  Loop
    Fetch c_emp Into r_emp;
    Exit When c_emp%NotFound;
dbms_output.put_line(r_emp.empno||’  ’||r_emp.ename||’  ’||r_emp.sal);
  End Loop;
  Close c_emp;
end;

带参数的显示游标

声明显式游标时可以带参数以提高灵活性

declare
   v_deptno emp.deptno%type; --部门编号变量
   cursor c_emp(dno number) is
        select empno,ename,sal from emp where deptno=dno; 
    r_emp c_emp%rowtype; --游标行
begin
  v_deptno:='&部门编号'; --输入参数值
  Open c_emp(v_deptno);--传递参数
  Loop
    Fetch c_emp Into r_emp;
    Exit When c_emp%NotFound;
dbms_output.put_line(r_emp.empno||'  '||r_emp.ename||'  '||r_emp.sal);
  End Loop;
  Close c_emp;
end;

循环游标

1、循环游标用于简化游标处理代码

2、当用户需要从游标中提取多行记录时使用

3、循环游标的语法如下:

FOR  record_name  IN  (corsor_name[(parameter[,parameter])...]) 
| (query_difinition)
LOOP
 statements
END LOOP;
DECLARE
	CURSOR c_emp  IS
       SELECT empno,ename,sal FROM  emp ORDER BY sal;
BEGIN
  FOR r_emp IN  c_emp  
Loop  -- r_emp代表游标行
    dbms_output.put_line(r_emp.empno||’’||r_emp.ename||’’||r_emp.sal);
  End Loop;	
END;

用于FOR循环的游标声明按照正常声明方式声明;不需要显式的打开,取数据,测试数据存在,关闭等;带参数时,in 游标名(参数)。

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

CURSOR <cursor_name> IS
	  select_statement FOR UPDATE [OF columns];

更新数据格式

UPDATE <table_name>
	SET column_name = column_value
	WHERE CURRENT OF <cursor_name>

删除数据格式

DELETE FROM <table_name>
WHERE CURRENT OF <cursor_name>
DECLARE 
   CURSOR c_emp IS
     SELECT empno,ename,sal FROM emp ORDER BY sal DESC FOR UPDATE;
   v_increase NUMBER:=0;    --增加的工资数
   v_new_sal NUMBER;    --新工资
BEGIN
   FOR r_emp IN c_emp LOOP
     v_new_sal:=r_emp.sal+v_increase;
     UPDATE emp SET sal=v_new_sal WHERE CURRENT OF c_emp;
     DBMS_OUTPUT.PUT_LINE(r_emp.empno||' '||r_emp.ename||
     '  old salary ='||r_emp.sal||'  new salary='||v_new_sal);
     v_increase:=v_increase+100;
   END LOOP;
END;

REF 游标

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

1、声明 REF 游标类型

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

2、声明 REF 游标类型的变量

ref_variable  ref_cursor_name;

打开游标变量的语法

OPEN ref_variable FOR   select_statement;
declare 
  type refcur is ref cursor;
  ref_cur refcur;
  r_emp   emp%rowtype;
  r_dept   dept%rowtype;
  selection varchar2(1):=upper(substr('&input',1,1));
begin  
  if selection='E'  then
     open ref_cur for select * from emp;
     dbms_output.put_line('=========员工信息=========');
     loop
         fetch ref_cur into r_emp;
         exit when ref_cur%notfound;
         dbms_output.put_line(r_emp.empno||'   '||r_emp.ename||'   '||r_emp.sal);        
     end loop;
 elsif  selection='D' then
   
     open ref_cur for select * from dept;
     dbms_output.put_line('=========部门信息=========');
     loop  
     fetch ref_cur into r_dept ;
     exit when ref_cur%notfound;
     dbms_output.put_line(r_dept.deptno||'  '||r_dept.dname||'   ');
     end loop;
  else
     dbms_output.put_line('请输入员工信息(E)或 部门信息(D)');
     return;     
  end if;
  close ref_cur;
end;

游标变量的优点和限制

1、游标变量的功能强大,可以简化数据处理。

2、游标变量的优点有:

(1)、可从不同的 SELECT 语句中提取结果集

(2)、可以作为过程的参数进行传递

(3)、可以引用游标的所有属性

(4)、可以进行赋值运算

3、使用游标变量的限制:

(1)、不能在程序包中声明游标变量

(2)、FOR UPDATE子句不能与游标变量一起使用

(3)、不能使用比较运算符

猜你喜欢

转载自blog.csdn.net/qq_36761831/article/details/88350770