数据库

位置:IT落伍者 >> 数据库 >> 浏览文章

Oracle学习手册:Oracle游标使用大全二


发布日期:2024年01月09日
 
Oracle学习手册:Oracle游标使用大全二

记录变量

定义一个记录变量使用TYPE命令和%ROWTYPE关于%ROWsTYPE的更多信息请参阅相关资料记录变量用于从游标中提取数据行当游标选择很多列的时候那么使用记录比为每列声明一个变量要方便得多当在表上使用%ROWTYPE并将从游标中取出的值放入记录中时如果要选择表中所有列那么在SELECT子句中使用*比将所有列名列出来要安全得多

例:

SET SERVERIUTPUT ON

DECLARE

R_emp EMP%ROWTYPE;

CURSOR c_emp IS SELECT * FROM emp;

BEGIN

OPEN c_emp;

LOOP

FETCH c_emp INTO r_emp;

EXIT WHEN c_emp%NOTFOUND;

DBMS_OUTPUTPUT_LINE(Salary of Employee||r_empename||is|| r_empsalary);

END LOOP;

CLOSE c_emp;

END;

%ROWTYPE也可以用游标名来定义这样的话就必须要首先声明游标:

SET SERVERIUTPUT ON

DECLARE

CURSOR c_emp IS SELECT enamesalary FROM emp;

R_emp c_emp%ROWTYPE;

BEGIN

OPEN c_emp;

LOOP

FETCH c_emp INTO r_emp;

EXIT WHEN c_emp%NOTFOUND;

DBMS_OUTPUTPUT_LINE(Salary of Employee||r_empename||is|| r_empsalary);

END LOOP;

CLOSE c_emp;

END;

带参数的游标

与存储过程和函数相似可以将参数传递给游标并在查询中使用这对于处理在某种条件下打开游标的情况非常有用它的语法如下:

CURSOR cursor_name[(parameter[parameter])] IS select_statement;

定义参数的语法如下:

Parameter_name [IN] data_type[{:=|DEFAULT} value]

与存储过程不同的是游标只能接受传递的值而不能返回值参数只定义数据类型没有大小

另外可以给参数设定一个缺省值当没有参数值传递给游标时就使用缺省值游标中定义的参数只是一个占位符在别处引用该参数不一定可靠

在打开游标时给参数赋值语法如下:

OPEN cursor_name[value[value]];

参数值可以是文字或变量

例:

DECALRE

CURSOR c_dept IS SELECT * FROM dept ORDER BY deptno;

CURSOR c_emp (p_dept VARACHAR) IS

SELECT enamesalary

FROM emp

WHERE deptno=p_dept

ORDER BY ename

r_dept DEPT%ROWTYPE;

v_ename EMPENAME%TYPE;

v_salary EMPSALARY%TYPE;

v_tot_salary EMPSALARY%TYPE;

BEGIN

OPEN c_dept;

LOOP

FETCH c_dept INTO r_dept;

EXIT WHEN c_dept%NOTFOUND;

DBMS_OUTPUTPUT_LINE(Department:|| r_deptdeptno||||r_deptdname);

v_tot_salary:=;

OPEN c_emp(r_deptdeptno);

LOOP

FETCH c_emp INTO v_enamev_salary;

EXIT WHEN c_emp%NOTFOUND;

DBMS_OUTPUTPUT_LINE(Name:|| v_ename|| salary:||v_salary);

v_tot_salary:=v_tot_salary+v_salary;

END LOOP;

CLOSE c_emp;

DBMS_OUTPUTPUT_LINE(Toltal Salary for dept:|| v_tot_salary);

END LOOP;

CLOSE c_dept;

END;

游标FOR循环

在大多数时候我们在设计程序的时候都遵循下面的步骤:

打开游标

开始循环

从游标中取值

检查那一行被返回

处理

关闭循环

关闭游标

可以简单的把这一类代码称为游标用于循环但还有一种循环与这种类型不相同这就是FOR循环用于FOR循环的游标按照正常的声明方式声明它的优点在于不需要显式的打开关闭取数据测试数据的存在定义存放数据的变量等等游标FOR循环的语法如下:

FOR record_name IN

(corsor_name[(parameter[parameter])]

| (query_difinition)

LOOP

statements

END LOOP;

下面我们用for循环重写上面的例子:

DECALRE

CURSOR c_dept IS SELECT deptnodname FROM dept ORDER BY deptno;

CURSOR c_emp (p_dept VARACHAR) IS

SELECT enamesalary

FROM emp

WHERE deptno=p_dept

ORDER BY ename

v_tot_salary EMPSALARY%TYPE;

BEGIN

FOR r_dept IN c_dept LOOP

DBMS_OUTPUTPUT_LINE(Department:|| r_deptdeptno||||r_deptdname);

v_tot_salary:=;

FOR r_emp IN c_emp(r_deptdeptno) LOOP

DBMS_OUTPUTPUT_LINE(Name: || v_ename || salary: || v_salary);

v_tot_salary:=v_tot_salary+v_salary;

END LOOP;

DBMS_OUTPUTPUT_LINE(Toltal Salary for dept:|| v_tot_salary);

END LOOP;

END;

在游标FOR循环中使用查询

在游标FOR循环中可以定义查询由于没有显式声明所以游标没有名字记录名通过游标查询来定义

DECALRE

v_tot_salary EMPSALARY%TYPE;

BEGIN

FOR r_dept IN (SELECT deptnodname FROM dept ORDER BY deptno) LOOP

DBMS_OUTPUTPUT_LINE(Department:|| r_deptdeptno||||r_deptdname);

v_tot_salary:=;

FOR r_emp IN (SELECT enamesalary

FROM emp

WHERE deptno=p_dept

ORDER BY ename) LOOP

DBMS_OUTPUTPUT_LINE(Name:|| v_ename|| salary:||v_salary);

v_tot_salary:=v_tot_salary+v_salary;

END LOOP;

DBMS_OUTPUTPUT_LINE(Toltal Salary for dept:|| v_tot_salary);

END LOOP;

END;

游标中的子查询

语法如下:

CURSOR C IS SELECT * FROM emp

WHERE deptno NOT IN (SELECT deptno

FROM dept

WHERE dname!=ACCOUNTING);

可以看出与SQL中的子查询没有什么区别

游标中的更新和删除

在PL/SQL中依然可以使用UPDATE和DELETE语句更新或删除数据行显式游标只有在需要获得多行数据的情况下使用PL/SQL提供了仅仅使用游标就可以执行删除或更新记录的方法

UPDATE或DELETE语句中的WHERE CURRENT OF子串专门处理要执行UPDATE或DELETE操作的表中取出的最近的数据要使用这个方法在声明游标时必须使用FOR UPDATE子串当对话使用FOR UPDATE子串打开一个游标时所有返回集中的数据行都将处于行级(ROWLEVEL)独占式锁定其他对象只能查询这些数据行不能进行UPDATEDELETE或SELECTFOR UPDATE操作

语法:

FOR UPDATE [OF [schema]lumn[[schema]lumn]

[nowait]

在多表查询中使用OF子句来锁定特定的表如果忽略了OF子句那么所有表中选择的数据行都将被锁定如果这些数据行已经被其他会话锁定那么正常情况下ORACLE将等待直到数据行解锁

在UPDATE和DELETE中使用WHERE CURRENT OF子串的语法如下:

WHERE{CURRENT OF cursor_name|search_condition}

例:

DELCARE

CURSOR c IS SELECT empnosalary

FROM emp

WHERE comm IS NULL

FOR UPDATE OF comm;

v_comm NUMBER();

BEGIN

FOR r IN c LOOP

IF rsalary< THEN

v_comm:=rsalary*;

ELSEIF rsalary< THEN

v_comm:=rsalary*;

ELSEIF rsalary< THEN

v_comm:=rsalary*;

ELSE

v_comm:=rsalary*;

END IF;

UPDATE emp;

SET comm=v_comm

WHERE CURRENT OF cl;

END LOOP;

END               

上一篇:ORACLE中dbms

下一篇:一句T-SQL语句引发的思考 转帖