- 记录类型语法
TYPE 类型名称 IS RECODE
(
成员名称 数据类型 [[NOT NULL] [:=默认值] 表达式 ],
...
成员名称 数据类型 [[NOT NULL] [:=默认值] 表达式 ]
);
- 案例1 声明并使用记录类型
DECLARE TYPE country_type IS RECORD
(
iso_code VARCHAR2(5),
name VARCHAR2(50)
);
TYPE country_tab IS TABLE OF country_type INDEX BY BINARY_INTEGER;
t_country country_tab;
BEGIN
-- Populate lookup
t_country(1).iso_code := 'UK';
t_country(1).name := 'United Kingdom';
t_country(2).iso_code := 'US';
t_country(2).name := 'United States of America';
t_country(3).iso_code := 'FR';
t_country(3).name := 'France';
-- Find country name for ISO code "DE"
<< lookup >>
FOR i IN 1 .. t_country.count LOOP
--IF t_country(i).iso_code = 'DE' THEN
DBMS_OUTPUT.PUT_LINE('ISO code "DE" = ' || t_country(i).name);
--EXIT lookup;
--END IF;
END LOOP;
END;
-----------------------------
ISO code "DE" = United Kingdom
ISO code "DE" = United States of America
ISO code "DE" = France
- 案例2
DECLARE
v_emp_empno emp.empno%TYPE ;
TYPE emp_type IS RECORD
(
ename emp.ename%TYPE ,
job emp.job%TYPE ,
hiredate emp.hiredate%TYPE ,
sal emp.sal%TYPE ,
comm emp.comm%TYPE
) ;
v_emp emp_type ; -- 定义一个指定的复合类型变量
BEGIN
v_emp_empno := &inputempno ;
SELECT ename,job,hiredate,sal,comm INTO v_emp
FROM emp WHERE empno=v_emp_empno ;
DBMS_OUTPUT.put_line('雇员编号:' || v_emp_empno || ',姓名:' || v_emp.ename || ',职位:' || v_emp.job || ',雇佣日期:' || TO_CHAR(v_emp.hiredate,'yyyy-mm-dd') || ',基本工资:' || v_emp.sal || ',佣金:' || NVL(v_emp.comm,0)) ;
EXCEPTION
WHEN others THEN
RAISE_APPLICATION_ERROR(-20007,'此雇员信息不存在!') ;
END ;
-----------------------------
输入参数:7499
雇员编号:7499,姓名:ALLEN,职位:SALESMAN,雇佣日期:1981-02-20,基本工资:1600,佣金:300
问题:使用记录类型和"表%ROWTYPE"有什么区别 上面的程序如果不使用记录类型,直接定义一个emp表的ROWTYPE对象,不是也可以完成吗? 解答:ROWTYPE固定结构,而TYPE由用户定义结构 使用ROWTYPE定义的变量其结构完全与表固定,而使用TYPE可以由用户自己来定义结构,在操作上会更加灵活;
- 案例3
DECLARE TYPE dept_type IS RECORD
(
deptno dept.deptno%TYPE:= 80, -- 定义默认值
dname dept.dname%TYPE,
loc dept.loc%TYPE
);
v_dept dept_type;
BEGIN
v_dept.dname := 'MLDN '; -- 为记录类型成员赋值
v_dept.loc := '北京'; -- 为记录类型成员赋值
DBMS_OUTPUT.put_line('部门编号:' || v_dept.deptno || ',名称:' || v_dept.dname || ',位置:' || v_dept.loc);
END;
-----------------------------
运行结果:
部门编号:80,名称:MLDN ,位置:北京
- 案例4 定义嵌套的记录类型
DECLARE TYPE dept_type IS RECORD
(
deptno dept.deptno%TYPE := 80, -- 定义默认值
dname dept.dname%TYPE ,
loc dept.loc%TYPE
);
TYPE emp_type IS RECORD
(
empno emp.empno%TYPE ,
ename emp.ename%TYPE ,
job emp.job%TYPE ,
hiredate emp.hiredate%TYPE ,
sal emp.sal%TYPE ,
comm emp.comm%TYPE ,
dept dept_type
);
v_emp emp_type ;
BEGIN
SELECT e.empno,e.ename,e.job,e.hiredate,e.sal,e.comm,d.deptno,d.dname,d.loc INTO
v_emp.empno,v_emp.ename,v_emp.job,v_emp.hiredate,v_emp.sal,v_emp.comm,v_emp.dept.deptno,v_emp.dept.dname,v_emp.dept.loc
FROM emp e,dept d
WHERE e.deptno=d.deptno AND e.empno=7369;
DBMS_OUTPUT.put_line('雇员编号:' || v_emp.empno || ',姓名:' || v_emp.ename || ',职位:' || v_emp.job || ',雇佣日期:' || TO_CHAR(v_emp.hiredate,'yyyy-mm-dd') || ',基本工资:' || v_emp.sal || ',佣金:' || NVL(v_emp.comm,0)) ;
DBMS_OUTPUT.put_line('部门编号:' || v_emp.dept.deptno || ',名称:' || v_emp.dept.dname || ',位置:' || v_emp.dept.loc) ;
END ;
-----------------------------
运行结果:
雇员编号:7369,姓名:SMITH,职位:CLERK,雇佣日期:1980-12-17,基本工资:800,佣金:0
部门编号:20,名称:RESEARCH,位置:DALLAS
分析:
本程序共定义了两个记录类型dept_type和emp_type,由于emp_type中要定义dept_type记录类型的成员,所以dept_type要在它使用之前定义,而后直接使用emp_type中的dept成员就可以访问dept_type的成员,从而完成操作的嵌套定义。
- 案例5 增加一条新的记录,利用记录类型保存数据
DECLARE TYPE dept_type IS RECORD
(
deptno dept.deptno%TYPE,
dname dept.dname%TYPE,
loc dept.loc%TYPE
);
v_dept dept_type;
BEGIN
v_dept.dname := 'MLDN';
v_dept.loc := '北京';
v_dept.deptno := 80;
INSERT INTO dept VALUES v_dept; -- 直接插入记录类型的数据
END;
-----------------------------
#在使用记录类型直接执行更新时,定义的记录类型中的成员顺序要与操作数据表的字段顺序保持一致,否则无法使用
- 案例6 修改数据,利用记录类型保存数据
DECLARE TYPE dept_type IS RECORD
(
deptno dept.deptno%TYPE,
dname dept.dname%TYPE,
loc dept.loc%TYPE
);
v_dept dept_type;
BEGIN
v_dept.dname := 'MLDNJAVA' ;
v_dept.loc := '中国' ;
v_dept.deptno := 80 ;
UPDATE dept SET ROW=v_dept WHERE deptno=v_dept.deptno ;
END;
-----------------------------
#在使用记录类型更新时,只需要在更新语句后写上ROW,就可以找到dname和loc,但是对于更新主键的限定条件,则还需要在where子句中编写
- 案例7 声明记录表(不支持创建记录表)
SQL> select * from test_emp1;
EMP_NO EMP_NAME
---------- --------------------
103 张三
104 李四
105 王五
SQL> select * from test_emp2;
EMP_NO EMP_NAME
---------- --------------------
103 张三
105 王五
106 赵六
DECLARE TYPE TEST_EMP IS RECORD
(
emp_no varchar2(10),
emp_name varchar2(20)
);
TYPE T_TYPE IS TABLE OF TEST_EMP;
V_TYPE1 T_TYPE;
V_TYPE2 T_TYPE;
V_TYPE3 T_TYPE;
BEGIN
SELECT emp_no,emp_name BULK COLLECT INTO V_TYPE1 FROM test_emp1;
SELECT emp_no,emp_name BULK COLLECT INTO V_TYPE2 FROM test_emp2;
V_TYPE3 := V_TYPE1 MULTISET union V_TYPE2;
-- 如下两行都不支持
--V_TYPE3 := V_TYPE1 MULTISET except V_TYPE2;
--SELECT V_TYPE1 MULTISET except V_TYPE2 INTO V_TYPE3 FROM DUAL;
FOR V_INDEX3 IN V_TYPE3.FIRST .. V_TYPE3.LAST LOOP
DBMS_OUTPUT.PUT_LINE(V_TYPE3(V_INDEX3).emp_no || ' ' || V_TYPE3(V_INDEX3).emp_name);
END LOOP;
END;
---------------------------------------
103 张三
104 李四
105 王五
103 张三
105 王五
106 赵六
---------------------------------------
#如上类型可在包头中定义
create or replace package MyRecType
is
TYPE TEST_EMP IS RECORD
(
emp_no varchar2(10),
emp_name varchar2(20)
);
TYPE T_TYPE IS TABLE OF TEST_EMP;
end;
declare v_emp_record_table MyRecType.T_TYPE;
begin
SELECT emp_no,emp_name BULK COLLECT INTO v_emp_record_table FROM test_emp1;
v_emp_record_table.extend();
v_emp_record_table(v_emp_record_table.count).emp_no :='104';
v_emp_record_table(v_emp_record_table.count).emp_name :='yyc';
for i in 1..v_emp_record_table.count loop
DBMS_OUTPUT.PUT_LINE(v_emp_record_table(i).emp_no || ',' || v_emp_record_table(i).emp_name);
end loop;
end;
-------------------------------------
103,张三
104,李四
105,王五
104,yyc
- 案例 8
DECLARE
TYPE t_row IS RECORD (
id NUMBER,
description VARCHAR2(50)
);
TYPE t_tab IS TABLE OF t_row;
l_tab t_tab := t_tab();
BEGIN
FOR i IN 1 .. 10 LOOP
l_tab.extend();
l_tab(l_tab.last).id := i;
l_tab(l_tab.last).description := 'Description for ' || i;
END LOOP;
END;
- 案例9 rowtype
CREATE TABLE t1 (
id NUMBER,
description VARCHAR2(50)
);
DECLARE
TYPE t_tab IS TABLE OF t1%ROWTYPE;
l_tab t_tab := t_tab();
BEGIN
FOR i IN 1 .. 10 LOOP
l_tab.extend();
l_tab(l_tab.last).id := i;
l_tab(l_tab.last).description := 'Description for ' || i;
END LOOP;
END;