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;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • ORACLE自学教程 --create tabletestone ( id number, --序号usernam...
    落叶寂聊阅读 1,064评论 0 0
  • 1. 了解SQL 1.1 数据库基础 ​ 学习到目前这个阶段,我们就需要以某种方式与数据库打交道。在深入学习MyS...
    锋享前端阅读 1,037评论 0 1
  • 5.多表查询 多表查询 目的:从多张表获取数据 前提:进行连接的多张表中有共同的列 等连接 通过两个表具有相同意义...
    乔震阅读 1,194评论 0 0
  • MySQL5.6从零开始学 第一章 初始mysql 1.1数据库基础 数据库是由一批数据构成的有序的集合,这些数据...
    星期四晚八点阅读 1,133评论 0 4
  • 1.存储过程简述 存储过程:它是大型数据库中常用的、一组为了完成特定功能的SQL语句集。 存储过程在Oracl中是...
    流泪海棠阅读 1,203评论 0 1