标量变量
用于存放单行单列的数据
---复合数据类型
PL/SQL记录
处理单行多列数据
PL/SQL集合
(1)索引表(Associative arrays, also known as index-by tables)
(2)嵌套表:一种用于处理PL/SQL数组的数据类型。嵌套表的元素下标从1开始,而且元素个数没有限制。
(3)变长数组
用于处理多行单列数据
(4)PL/SQL记录表
处理多行多列数据
1.pl/sql记录
TYPE type_name IS RECORD(
field_declaration1[,field_declaration2]...
);
identifier type_name;
type_name:记录类型的名称(IS RECORD 表示记录类型)
field_declaration:记录成员的定义,多个记录成员之间用逗号(,)隔开.
identifier:指定记录变量名
方法一:
type emp_record_type is record(
names emp.ename%type,
salary emp.sal%type,
dno emp.deptno%type
);
emp_record是基于记录类型emp_record_type所定义的记录变量
emp_record emp_record_type;
方法2:
%rowtype属性能够基于表或者视图定义记录变量
identified table_name%rowtype;
or
identified view_name%rowtype;
dept_record dept%rowtype;
获取雇员姓名 ,薪水,部门号
set serveroutput on;
declare
type emp_record_type is record(
names emp.ename%type,
salary emp.sal%type,
dno emp.deptno%type
);
emp_record emp_record_type;
begin
---select ename,sal,deptno into emp_record from emp where empno=&no;
select ename,sal,deptno into emp_record.names,emp_record.salary,emp_record.dno from emp where empno=&no;
dbms_output.put_line('names: '||emp_record.names);
dbms_output.put_line('salary: '||emp_record.salary);
dbms_output.put_line('dno: '||emp_record.dno);
end;
在insert 的values字句中使用记录变量/记录成员,向dept表中插入一条数据
set serveroutput on;
declare
dept_record dept%rowtype;
begin
dept_record.deptno :=&no;
dept_record.dname := '&names';
dept_record.loc :='&city';
---insert into dept(deptno,dname,loc) values(dept_record.deptno,dept_record.dname,dept_record.loc);
insert into dept values dept_record;
end;
2.嵌套表(nested table)
嵌套表一种用于处理PL/SQL数组的数据类型。嵌套表的元素下标从1开始,而且元素个数没有限制。
语法:
table type_name is table of element_type;
identifier type_name;
type_name指嵌套表的类型名。
element_type指嵌套表元素的数据类型。
identifier指嵌套表变量。
使用嵌套表元素时,须要先使用构造方法初始化嵌套表
set serveroutput on;
declare
type ename_table_type is table of emp.ename%type;
ename_table ename_table_type;
begin
ename_table :=ename_table_type('y1','y2');
select ename into ename_table(1) from emp where empno=&no;
dbms_output.put_line('employee name: ' || ename_table(1));
dbms_output.put_line('employee name: ' || ename_table(2));
end;
定义一个表 ename_table初始化有两行数据y1,y2 把y1的值改成&no的ename
y2没有改输出时还显示y2,此表只能插入两行数据
3.集合方法
COUNT, DELETE, EXISTS, EXTEND, FIRST, LAST, LIMIT, NEXT, PRIOR, and TRIM
4.批量绑定
forall语法
forall index in lower_bound..upper_bound
sql_statement;
index隐含定义的整形变量(做为集合元素下标使用)
lower_bound|upper_bound集合元素的上界和下界。
forall批量插入
create table tmp01(id numvber primary key,name varchar2(50));
declare
type id_table_type is table of number index by binary_integer;
type name_table_type is table of varchar2(10) index by binary_integer;
id_table id_table_type;
name_table name_table_type;
start_time number;
end_time number;
begin
for i in 1..5000 loop
id_table(i):=i;
name_table(i):='name'||i;
end loop;
start_time:=DBMS_UTILITY.GET_TIME;
forall i in 1..id_table.count
insert into tmp01 values(id_table(i),name_table(i));
end_time:=dbms_utility.get_time;
commit;
dbms_output.put_line('total time is '||to_char((end_time-start_time)/100));
end;
for循环单行插入
truncate table tmp01 ;
declare
type id_table_type is table of number index by binary_integer;
type name_table_type is table of varchar2(10) index by binary_integer;
id_table id_table_type;
name_table name_table_type;
start_time number;
end_time number;
begin
for i in 1..5000 loop
id_table(i):=i;
name_table(i):='name'||i;
end loop;
start_time:=DBMS_UTILITY.GET_TIME;
for i in 1..5000 loop
insert into tmp01 values(id_table(i),name_table(i));
end loop;
commit;
end_time:=dbms_utility.get_time;
dbms_output.put_line('total time is '||to_char((end_time-start_time)/100));
end;
5.索引表
---语法
TYPE type_name IS TABLE OF element_type [NOT NULL] INDEX BY key_type;
indentifer type_name;
type_name指定用户自定义数据类型名称
element_type 指定索引表元素的数据类型
key_type指定索引表元素下标的数据类型(varchar2,binary_integer,pls_integer等)
indentifer指定索引表变量
索引表的下标能够为负值,并且元素个数没有限制。
set serveroutput on;
declare
type ename_table_type is table of emp.ename%type index by binary_integer;
ename_table ename_table_type;
begin
select ename into ename_table(1) from emp where empno=&no;
dbms_output.put_line('employee name : ' || ename_table(1));
end;
set serveroutput on;
declare
type city_table_type is table of number index by varchar2(10);
city_table city_table_type;
begin
city_table('zhouzq'):=1;
city_table('lidd'):=2;
city_table('lijian'):=3;
dbms_output.put_line('the first element: ' || city_table.first);
dbms_output.put_line('the last element: ' || city_table.last);
end;
-- 定义记录集
TYPE yang_rec IS RECORD( ename varchar2(30), eid NUMBER );
-- 定义索引表类型
TYPE yang_tab IS TABLE OF yang_rec INDEX BY BINARY_INTEGER;
-- 定义索引表对象的实例
test_tab yang_tab;
对索引表中进行操做
1) 插入:见上例。
2) 引用:
IF emps.EXIST(10) THEN
DBMS_OUTPUT.PUT_LINE('存在第10条记录。');
END IF;
3) 修改:
修改emps 表中的第100个条目:
emps(100).emp_name := 'yang linker';
4) 删除:
-- 删除emps 表中的第100个条目:
emps.DELETE(100);
-- 删除emps 表中的从1到100的条目:
emps.DELETE(1, 100);
-- 删除emps 表中的的全部条目:
emps.DELETE;
索引表中的函数
1) count:返回表的条目数量:
num_rows := emps.COUNT;
2) EXISTS:若是指定的条目存在,则返回为真;不然为假。
IF emps.EXIST(10) THEN
DBMS_OUTPUT.PUT_LINE('存在第10条记录。');
END IF;
3) LIMIT:该方法返回集合能够包含的最大元素数目。只有变长数组才有上限。将LIMIT 用于嵌套表和索引
表时,其返回为NULL。
4) FRIST:该方法返回集合中使用的最小的索引值。
5) LAST:该方法返回集合中使用的最大的索引值。
6) NEXT:该方法返回集合中当前使用的下一个索引值。
7) PRIOR:该方法返回集合中当前使用的上一个索引值。
8) DELETE:删除集合中的条目,见前例。
9) TRIM:从集合的尾部删除一个或多个条目,无返回值,只适用于变长数组和嵌套表。
emps.TRIM(1); -- 从集合的尾部删除一个条目
emps.TRIM(3); -- 从集合的尾部删除三个条目
10) EXTEND:在集合的尾部添加条目或复制已有的条目,只适用于变长数组和嵌套表。
emps.EXTEND(1); -- 从集合的尾部添加一个条目
emps.EXTEND(3); -- 从集合的尾部添加三个条目
emps.EXTEND(1, 3);-- 复制集合的第三个条目,并将其添加到表的末尾。
6.游标
使用显示游标包括定义游标,打开游标,提取游标和关闭游标。
(1)定义游标
CURSOR cursor_name IS select_statement;
(2)打开游标
OPEN cursor_name;
(3)提取游标
---提取一行
FETCH cursor_name into var1,var2...;
---提取多行
FETCH cursor_name BULK COLLECT INTO collect1,collect2...[LIMIT rows];
---collect1用于指定接受游标的集合变量
(4)关闭游标
CLOSE cursor_name;
显示游标属性:%isopen,%found,%notfound,%rowcount
---显示游标中使用fetch...into
set serveroutput on;
declare
cursor emp_cursor is select ename,sal from emp where deptno=10;
v_name emp.ename%type;
v_salary emp.sal%type;
begin
open emp_cursor;
fetch emp_cursor into v_name,v_salary;
for ename,sal in v_name,v_salary
loop
dbms_output.put_line('ename: '||ename);
dbms_output.put_line('salary: '||sal );
end loop;
close emp_sursor;
end;
set serveroutput on;
declare
cursor emp_cursor is select ename,sal from emp where deptno=10;
v_ename emp.ename%type;
v_salary emp.sal%type;
begin
open emp_cursor;
loop
fetch emp_cursor into v_ename,v_salary;
exit when emp_cursor%notfound;
dbms_output.put_line(v_ename || ' : ' || v_salary);
end loop;
close ename_cursor;
end;
显示游标中使用fetch...bulk collect into
###显示部门10的全部雇员名
set serveroutput on;
declare
type ename_table_type is table of emp.ename%type;
ename_table ename_table_type;
cursor ename_cursor is select ename from emp where deptno=10;
begin
open ename_cursor;
fetch ename_cursor bulk collect into ename_table;
for i in 1..ename_table.count
loop
dbms_output.put_line(i||':'||ename_table(i));
end loop;
close ename_cursor;
set serveroutput on;
declare
cursor ename_cursor is select ename from emp where deptno=10;
begin
open ename_cursor;
fetch ename_cursor bulk collect into ename_table;
for i in 1..ename_table.count
loop
dbms_output.put_line(i||':'||ename_table(i));
end loop;
close ename_cursor;
end;
---游标FOR循环
语法:
FOR record_name IN cursor_name loop
statement1;...
end loop;
cursor_name:已定义的游标名称
record_name:隐含定义的记录变量名
在执行循环体内容以前,oracle会隐含地打开游标,而且每循环一次提取一次数据,提取完全部数据后,会自动退出循环并隐含关闭游标。
---FOR循环游标
set serveroutput on;
declare
cursor ename_cursor is select ename from emp;
begin
for cc_record in ename_cursor loop
dbms_output.put_line(ename_cursor%rowcount ||': ' || cc_record.ename);
end loop;
end;
---游标FOR循环中直接使用子查询
set serveroutput on;
begin
for cc_record in (select ename from emp where deptno=10) loop
DBMS_OUTPUT.PUT_LINE(cc_record.ename);
end loop;
end;
sql