Oracle12C(集合)之03-记录类型,ROWTYPE

  1. 记录类型语法
TYPE 类型名称 IS RECODE
(
成员名称 数据类型 [[NOT NULL] [:=默认值] 表达式 ],
...
成员名称 数据类型 [[NOT NULL] [:=默认值] 表达式 ]
);
  1. 案例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
  1. 案例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可以由用户自己来定义结构,在操作上会更加灵活;

  1. 案例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 ,位置:北京
  1. 案例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的成员,从而完成操作的嵌套定义。
  1. 案例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;
-----------------------------
#在使用记录类型直接执行更新时,定义的记录类型中的成员顺序要与操作数据表的字段顺序保持一致,否则无法使用
  1. 案例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子句中编写
  1. 案例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
  1. 案例 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;
  1. 案例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;

你可能感兴趣的:(Oracle12C(集合)之03-记录类型,ROWTYPE)