一、 实验目的

《数据库开发技术》课程之实验六

PL/SQL 复合数据类型:记录、表和可变数组

1.    掌握如何创建 PL/SQL 记录   。

2.    会用%ROWTYPE      属性创建一个记录。

3.    掌握如何创建 PL/SQL 表和记录表。

4.    掌握那些能获得复合数据信息的内置方法的使用。

5.    掌握可变数组的使用。

二、 实验内容和要求

1.    根据表 emp 的全部字段定义记录变量 emp_record。用 SELECT 语句将编号为 7788 的雇员的全部字

段对应地存入该记录变量,最后输出记录变量的雇员名称字段 emp_record.ename 和雇员工资字段

的内容。

SET SERVEROUTPUT ON

DECLARE

emp_record emp%ROWTYPE;              –定义记录变量

BEGIN

SELECT * INTO emp_record

FROM    emp

WHERE  empno = 7788;                  –取出一条记录

DBMS_OUTPUT.PUT_LINE(emp_record.ename||’的工资为:’||

To_char(emp_record.sal));   –输出记录变量的某个字段

END;

执行结果如下:

SCOTT 的工资为:3000

PL/SQL 过程已成功完成。

2.    声明一张 Index_By 表,用来接收并存储 DEPT 表的信息,把部门号作为键,不要忘记部门号是 10

的倍数。使用循环从 DEPT 表中将所有部门信息检索到 PL/SQL 记录表中,然后用另一个循环来显

示表中的这些信息。

DECLARE

TYPE dept_list_type IS TABLE OF dept%ROWTYPE index by binary_integer;

dept_list dept_list_type;

v_count number(3);

BEGIN

SELECT count(*) INTO v_count FROM dept;

FOR counter IN 1..v_count LOOP

SELECT * INTO dept_list(counter*10) FROM dept

WHERE deptno=counter*10;

END LOOP;

FOR COUNTER IN 1..v_count LOOP

DBMS_OUTPUT.PUT_LINE(to_char(dept_list(counter*10).deptno)||’, ‘||

dept_list(counter*10).dname||’, ‘||dept_list(counter*10).loc);

END LOOP;

END;

/

执行结果为:

10, ACCOUNTING, NEW YORK

20, RESEARCH, DALLAS

30, SALES, CHICAGO

40, OPERATIONS, BOSTON

PL/SQL 过程已成功完成。

3.    阅读以下程序,找出出错之处,说明出错原因,预测运行输出结果是什么。请删改错误,加上适当

注释后,运行该程序,验证自己的预测是否正确。(注:实验报告中只要指出出错的语句和出错的原因

即可,不要抄原程序!)

SET SERVEROUTPUT ON

DECLARE

TYPE dept_list IS TABLE OF dept.dname%TYPE;                  –定义嵌套表

TYPE top5_list IS VARRAY(5) OF dept.loc%TYPE;                –定义可变数组

dis_dept dept_list;                                                                          –嵌套表的声明

num_5 top5_list;                                                                            –可变数组的声明

BEGIN

/*  下 面的这 条                                  dis_dept(1):=’AMGN’    赋值 语句是 非 法的, 因为 集合 尚未初始 化。出 现错 误提示

(ORA-06531: 引用未初始化的集合,是以下 ORA-06531  Reference  to  uninitialized  collection 的翻

译)。集合变量的初始化是通过调用集合的构造函数来实现的,集合构造函数与集合对象(而不是集合

变量)同名。改正的方法有二。一是在集合变量声明的同时进行初始化,例如:

dis_dept dept_list :=dept_list(‘AMGN’, ‘BGEN’); 也可以在变量声明之后再进行初始化,例如:

dis_dept dept_list;

……

dis_dept :=dept_list(‘AMGN’,’BGEN’);

本题则可以直接将下面的这条 dis_dept(1):=’AMGN’      语句删除即可。

*/

— dis_dept(1):=’AMGN’;

IF dis_dept IS NULL THEN

–显式调用构造函数进行集合的初始化

dis_dept :=dept_list(‘AMGN’,’BGEN’);

DBMS_OUTPUT.PUT_LINE(‘dis_dept 表当前元素个数为:’||to_char(dis_dept.count));

END IF;

num_5:=top5_list(‘ORCL’,’CSCO’,NULL,NULL);

IF num_5(3) IS NULL THEN

num_5(3):=’CPQ’;

END IF;

num_5(4):=’DELL’;

FOR COUNTER IN 1..4 LOOP

DBMS_OUTPUT.PUT_LINE(NUM_5(COUNTER));

END LOOP;

END;

/

执行结果为:

dis_dept 表当前元素个数为:2

ORCL

CSCO

CPQ

DELL

PL/SQL 过程已成功完成。

以下是另一个相关的例子:

SET SERVEROUTPUT ON

DECLARE

TYPE dept_list IS TABLE OF dept.dname%TYPE;                  –定义嵌套表

TYPE top5_list IS VARRAY(5) OF dept.loc%TYPE;                –定义可变数组

dis_dept dept_list;                                                                          –嵌套表的声明

num_5 top5_list;                                                                            –可变数组的声明

v_count number(3);

BEGIN

IF dis_dept IS NULL THEN

–嵌套表要显式调用构造函数进行集合的初始化

dis_dept :=dept_list(‘AMGN’,’BGEN’);

DBMS_OUTPUT.PUT_LINE(‘dis_dept 表当前元素个数为:’||to_char(dis_dept.count));

dis_dept.extend(2);

dis_dept(3):=’EXTEND_ELEMENT’;

v_count:=dis_dept.count;

–嵌套表必须使用 extend(n)动态增加元素

DBMS_OUTPUT.PUT_LINE(‘dis_dept 表扩充后的元素个数为:’||to_char(dis_dept.count));

FOR i IN 1.. v_count loop                                    –输出嵌套表 dis_dept 的内容

DBMS_OUTPUT.PUT_LINE(dis_dept(i));

END LOOP;

END IF;

num_5:=top5_list(‘ORCL’,’CSCO’,NULL,NULL);

IF num_5(3) IS NULL THEN

num_5(3):=’CPQ’;

END IF;

num_5(4):=’DELL’;

FOR COUNTER IN 1..4 LOOP

DBMS_OUTPUT.PUT_LINE(NUM_5(COUNTER));

END LOOP;

END;

/

执行结果为:

dis_dept 表当前元素个数为:2

dis_dept 表扩充后的元素个数为:4

AMGN

BGEN

EXTEND_ELEMENT

ORCL

CSCO

CPQ

DELL

PL/SQL 过程已成功完成。

4.    *将上题改为使用 INDEX BY BINARY_INTEGER 的索引表,则实现同一执行结果,程序要做哪些

相应的改变。

DECLARE

TYPE dept_list IS TABLE OF dept.dname%TYPE index by binary_integer;    –定义索引组织表

TYPE top5_list IS VARRAY(5) OF dept.loc%TYPE;

dis_dept dept_list;

num_5 top5_list;

BEGIN

dis_dept(1):=’AMGN’;                                                                                  –为表元素赋值

IF not dis_dept.exists(2) THEN

dis_dept(2) :=’BGEN’;

DBMS_OUTPUT.PUT_LINE(‘dis_dept 表当前元素个数为:’||to_char(dis_dept.count));

END IF;

num_5:=top5_list(‘ORCL’,’CSCO’,NULL,NULL);

IF num_5(3) IS NULL THEN

num_5(3):=’CPQ’;

END IF;

num_5(4):=’DELL’;

FOR COUNTER IN 1..4 LOOP

DBMS_OUTPUT.PUT_LINE(NUM_5(COUNTER));

END LOOP;

END;

/

执行结果为:

dis_dept 表当前元素个数为:2

ORCL

CSCO

CPQ

DELL

PL/SQL 过程已成功完成。

以下是与上题对应的另一个相关的例子:

SET SERVEROUTPUT ON

DECLARE

TYPE dept_list IS TABLE OF dept.dname%TYPE index by binary_integer;            –定义索引组织表

TYPE top5_list IS VARRAY(5) OF dept.loc%TYPE;                                                    –定义可变数组

dis_dept dept_list;                                                                                                              –索引表的声明

num_5 top5_list;                                                                                                                  –可变数组的声明

v_count number(3);

BEGIN

dis_dept(1):=’AMGN’;                                                                                                      –为表元素赋值

IF not dis_dept.exists(2) THEN

DBMS_OUTPUT.PUT_LINE(‘dis_dept 表当前元素个数为:’||to_char(dis_dept.count));

— dis_dept.extend(2);

dis_dept(3):=’EXTEND_ELEMENT’;

v_count:=dis_dept.count;

–索引表无须使用 extend(n)增加元素,使用了反而出错

DBMS_OUTPUT.PUT_LINE(‘dis_dept 表增添元素后的个数为:’||to_char(dis_dept.count));

FOR i IN 1.. v_count loop

DBMS_OUTPUT.PUT_LINE(dis_dept(i));

END LOOP;

END IF;

num_5:=top5_list(‘ORCL’,’CSCO’,NULL,NULL);

IF num_5(3) IS NULL THEN

num_5(3):=’CPQ’;

END IF;

num_5(4):=’DELL’;

FOR COUNTER IN 1..4 LOOP

DBMS_OUTPUT.PUT_LINE(NUM_5(COUNTER));

END LOOP;

END;

/

执行结果为:

dis_dept 表当前元素个数为:2

dis_dept 表增添元素后的个数为:3

AMGN

BGEN

EXTEND_ELEMENT

ORCL

CSCO

CPQ

DELL

PL/SQL 过程已成功完成。

附加题:

*分割省份信息放入嵌套表结构中。用户输入:湖南|河南|江西,按”|”分割省份。

1)  接受用户输入

2)  分割字符串,把省份分割出放入嵌套表结构中

3)  遍历输出嵌套表

提示:str := ‘&STR’                          — str:= ‘湖南|河南|江西’;

SET SERVEROUTPUT ON

DECLARE

TYPE prov_type IS TABLE OF varchar(15);                –定义嵌套表

prov_list prov_type:=prov_type();                                  –嵌套表的声明与初始化

str varchar(150);

v_loc number(3);

v_count number(2):=1;

BEGIN

str:= ‘&STR’;    — str:= ‘湖南|河南|江西’;

LOOP

v_loc :=instr(str,’|’,1);

prov_list.extend;

IF v_loc=0 THEN

prov_list(v_count):=str;

EXIT;

ELSE

prov_list(v_count):=substr(str,1,v_loc-1);

str:=substr(str,v_loc+1);

v_count:=v_count+1;

END IF;

END LOOP;

DBMS_OUTPUT.PUT_LINE(‘用户输入的省份显示如下:’);

FOR i IN 1.. v_count loop                                    –输出嵌套表 prov_list 的内容

DBMS_OUTPUT.PUT_LINE(prov_list(i));

END LOOP;

END;

/

5.    参照教材和课件中的相关例子,自选实例使用复合数据的各种内置方法。

三、 实验报告

根据实验内容要求写出相应的  PL/SQL  程序,并记录实验过程中遇到的困难和解决问

题的方法。(实验报告中不要求写加*题目和附加题的实验过程和内容)