http://www.cnblogs.com/kingjiong/archive/2009/02/19/1393837.html
1. 使用%TYPE
在许多情况下,PL/SQL变量可以用来存储在数据库表中的数据。在这种情况下,变量应该拥有与表列相同的类型。例如,students表的first_name列的类型为VARCHAR2(20),我们可以按照下述方式声明一个变量:
DECLARE
v_FirstName VARCHAR2(20);
但是如果first_name列的定义改变了会发生什么(比如说表改变了,first_name现在的类型变为VARCHAR2(25))?那就会导致所有使用这个列的PL/SQL代码都必须进行修改。如果你有很多的PL/SQL代码,这种处理可能是十分耗时和容易出错的。
这时,你可以使用”%TYPE”属性而不是将变量类型硬性编码。
例如:
DECLARE
v_FirstName students.first_name%TYPE;
通过使用%TYPE,v_FirstName变量将同students表的first_name列的类型相同(可以理解为将两者邦定起来)。
每次匿名块或命名块运行该语句块以及编译存储对象(过程、函数、包、对象类和触发器)时,就会确定该类型。
使用%TYPE是非常好的编程风格,因为它使得PL/SQL更加灵活,更加适应于对数据库定义的更新。
2. 使用%ROWTYPE
2.1 PL/SQL记录
PL/SQL记录类型类似于C语言中的结构,是一种复合类型,是用户自定义的。
记录提供了一种处理独立的但又作为一个整体单元相关的变量的机制。请看:
DECLARE
v_StudentID NUMBER(5);
v_FirstName VARCHAR2(20);
v_LastName VARCHAR2(20);
这3个变量在逻辑上是相互关联的,因为他们指向students表中不同的字段。如果为这些变量声明一个记录类型,那么他们之间的关系就十分明显,可作为一个单元进行处理。
DECLARE
/*Define a record type to hold common student informationi*/
TYPE t_StudentRecord IS RECORD(
StudentID NUMBER(5),
FirstName VARCHAR2(20),
LastName VARCHAR2(20);
/*Declare a variable of this type.*/
v_StudentInfo t_StudentRecord;
2.2 记录赋值
可以用SELECT语句向记录赋值,这将会从数据库中检索数据并将该数据存储到记录中。注意的是,记录中字段应该和查询结果列表中的字段相匹配。
SELECT studentID,firstName,lastName
into v_StudentInfo
from students where studentID=32;
2.3 使用%ROWTYPE
在PL/SQL中将一个记录声明为具有相同类型的数据库行的作法是很常见的。PL/SQL提供了%ROWTYPE运算符,使得这样的操作更为方便。
例如:
DECLARE
v_RoomRecord rooms%ROWTYPE;
将定义一个记录,该记录中的字段将与rooms表中的列相对应。
http://www.linuxidc.com/Linux/2011-04/35222.htm
//%type
//如果声明的变量是直接映射到数据库的某一列上,那么就可以使用%type关键字将变量
//锚定到这个列上。这样做有什么好处呢?
//比如:
//declare v_ename scott.emp.ename%type;
//当数据类型发生变化时,此方法显得非常灵活。
//如果更改了列的长度,那么锚定到该列上的所有变量都会自动更改其长度;
//假设我们将v_ename定义为varchar2(10),那么当emp表中的ename列发生变化时,
//我们得手动将v_enam更改为emp.ename相同的数据长度;
//当我们使用锚定类型后,变量就会自动进行调整。
//%rowtype
//%rowtype与%type相似;不过它将变量锚定到表的所有列,而不是锚定到某一列;
//更多关于%rowtype与%type,
//请参考:http://blog.csdn.net/BOBO12082119/archive/2010/12/02/6051367.aspx
//下面是一个实例:
create table dept(
deptno varchar2(5),
dname varchar2(20),
loc varchar2(20)
);
create or replace procedure pro_insert(
deptno_in in dept.deptno%type,
dname_in in dept.dname%type,
loc_in in dept.loc%type
)
as
v_dept dept%rowtype;
begin
begin
insert into dept
select deptno_in,dname_in,loc_in
from dual;
commit;
dbms_output.put_line('inserting successed');
exception
when others then
rollback;
end;
begin
select deptno_in,dname_in,loc_in
into v_dept from dual;
dbms_output.put_line(
'The data having been inserted.'||
'deptno:'||v_dept.deptno||
',dname:'||v_dept.dname||
',loc:'||v_dept.loc
);
end;
end pro_insert;
//
//上面的过程中,使用到了嵌套块;
//所谓嵌套块就是块中包含其他子块;
//嵌套块允许出现在代码块的异常处理部分和执行部分,
//但是不允许出现在声明中。
//
SQL> set serveroutput on;
SQL> exec pro_insert('111','财务部','福州');
inserting successed
The data having been inserted.deptno:111,dname:财务部,loc:福州
PL/SQL procedure successfully completed
//
//从这里看出来,%rowtype定义的变量作用有点相似游标,
//但是我们不能将%rowtype定义的变量当做游标来使用,
//否则我们将会得到下面的错误:
//ORA-01422: exact fetch returns more than requested number of rows
declare v_dept dept%rowtype;
begin
select deptno,dname,loc
into v_dept
from dept;
dbms_output.put_line(
'The data having been inserted.'||
'deptno:'||v_dept.deptno||
',dname:'||v_dept.dname||
',loc:'||v_dept.loc
);
end;
//
//下面我们用游标来实现上面的操作,具体看下面的匿名块:
declare
cursor cv_dept is
select *
from dept;
begin
//变量v_dept不必我们显示声明
//for循环会为我们隐式的打开和关闭游标,不必我们现实的打开和关闭游标
for v_dept in cv_dept loop
dbms_output.put_line(
'deptno:'||v_dept.deptno||
',dname:'||v_dept.dname||
',loc:'||v_dept.loc
);
end loop;
end;
//
deptno:111,dname:财务部,loc:福州
deptno:120,dname:销售部,loc:大连
deptno:130,dname:科研部,loc:北京
PL/SQL procedure successfully completed