PL/SQL嵌套记录与记录集合

PL/SQL嵌套记录与记录集合

转自:http://blog.csdn.net/leshami/article/details/7569673

将多个逻辑上不相关列组合到一起形成了PL/SQL的记录类型,从而可以将记录类型作为一个整体对待来处理。
而且PL/SQL记录类型可以进行嵌套以及基于PL/SQL记录来定义联合数组,嵌套表等。
本文首先回顾了PL/SQL记录的几种声明形式,接下来主要描述PL/SQL记录的嵌套以及基于记录的集合。

1、下面的示例同时描述了基于表,基于游标,以及基于用户自定义的记录  

DECLARE  
    rec_tab            dept%ROWTYPE;                        -->基于表类型使用ROWTYPE来声明记录变量       
    v_counter        PLS_INTEGER := 0;  
 
    CURSOR cur_tab IS                                            -->声明游标   
          SELECT dname, loc FROM dept;  
 
    rec_cur_tab    cur_tab%ROWTYPE;                  -->基于定义的游标使用ROWTYPE来声明记录变量       
 
    TYPE dept_rec_type IS RECORD                      -->用户自定义记录类型   
    (  
          dname    dept.dname%TYPE                          -->可以使用TYPE属性,也可以使用自定义的数据类型   
        ,loc        dept.loc%TYPE  
    );  
 
    dept_rec          dept_rec_type;                      -->基于自定义的记录类型来声明记录变量       
BEGIN  
    SELECT *  
    INTO rec_tab                                                  -->使用select into为记录变量赋值   
    FROM dept  
    WHERE deptno = 10;  
 
    DBMS_OUTPUT.put_line( '------- First print record based on table--------' );  
    DBMS_OUTPUT.put_line( 'Record is ' || rec_tab.dname || ',' || rec_tab.loc );  
 
    OPEN cur_tab;  
 
    DBMS_OUTPUT.put_line( '------- Next print record based on cursor--------' );  
 
    LOOP  
          FETCH cur_tab INTO rec_cur_tab;        -->使用fetch into为记录变量赋值       
 
          EXIT WHEN cur_tab%NOTFOUND;  
          v_counter    := v_counter 1;  
          DBMS_OUTPUT.put_line( 'Record ' || v_counter || ' is ' || rec_cur_tab.dname || ',' || rec_cur_tab.loc );  
    END LOOP;  
 
    CLOSE cur_tab;  
 
    SELECT dname, loc                                        -->对自定义的记录变量赋值             
    INTO    dept_rec  
    FROM    dept  
    WHERE  deptno = 20;  
 
    DBMS_OUTPUT.put_line( '------- Finally print record based on user defined record--------' );  
    DBMS_OUTPUT.put_line( 'Record is ' || dept_rec.dname || ',' || dept_rec.loc );  
END;  
 
 
2、记录的赋值与引用  

DECLARE  
    TYPE rec1_t IS RECORD            -->声明自定义记录类型   
    (  
          field1    VARCHAR2( 16 )  
        ,field2    DATE  
    );  
 
    TYPE rec2_t IS RECORD            -->声明自定义记录类型   
    (  
          id        INTEGER NOT NULL:= -1      -->注意,此时使用NOT NULL约束,因此要赋初值,否则报错   
        ,name    VARCHAR2( 64 ) NOT NULL:= '[anonymous]'  
    );  
 
    rec1    rec1_t;                          -->声明自定义记录类型变量rec1和rec2   
    rec2    rec2_t;  
BEGIN  
    rec1.field1 := 'Yesterday';      -->赋值与引用时,使用record_name.field_name方式   
    rec1.field2 := TRUNC( SYSDATE - 1 );  
    DBMS_OUTPUT.put_line( 'rec1 values are ' || rec1.field1 || ',' || rec1.field2 );  
    DBMS_OUTPUT.put_line(  'rec2 values is '||rec2.name );  
END;  
 
3、为记录赋缺省值
 
DECLARE  
    TYPE recordtyp IS RECORD  
    (  
          field1    NUMBER  
        ,field2    VARCHAR2( 32 ) DEFAULT 'something'  
    );  
 
    rec1    recordtyp;  
    rec2    recordtyp;  
BEGIN  
    -- 下面为变量rec1赋值   
    rec1.field1 := 100;  
    rec1.field2 := 'something else';  
    --下面通过使用变量rec2将其值赋给rec1,则rec1恢复到原始状态,即Field1为NULL,field2为something   
    rec1 := rec2;  
    DBMS_OUTPUT.put_line( 'Field1 = ' || NVL( TO_CHAR( rec1.field1 ), '' ) || ',  
                                                field2 = ' || rec1.field2 );  
END;  
 
4、记录类型作为过程的参数进行传递  

DECLARE  
    TYPE emp_rec_type IS RECORD                                                            -->自定义记录类型   
    (  
          eno        NUMBER( 6 )  
        ,esal      NUMBER( 8, 2 )  
        ,ename    VARCHAR2( 10 )  
    );  
 
    emp_info    emp_rec_type;                                                                  -->声明记录类型变量   
 
    PROCEDURE raise_salary( emp_info IN OUT emp_rec_type ) IS -->本地过程用于增加雇员薪水,其参数为IN OUT 型记录类型   
    BEGIN  
          UPDATE emp  
          SET sal = sal sal * emp_info.esal  
          WHERE empno = emp_info.eno  
          RETURNING ename, sal                                                                    -->使用returning 子句将ename以及更新后的薪水赋值给记录变量       
          INTO emp_info.ename, emp_info.esal;  
    END raise_salary;  
BEGIN                                                                                                              -->主程序块   
    emp_info.eno := 7788;                                                                        -->对记录变量赋值,此时emp_info.ename为NULL,由调用过程生成     
    emp_info.esal := 0.5;  
    raise_salary( emp_info );  
    DBMS_OUTPUT.put_line( 'User ' || emp_info.ename || '''s new salary is ' || emp_info.esal );  
END;  
 
5、嵌套记录  

可以在记录类型中包含对象、集合和其他的记录(又叫嵌套记录)。但是对象类型中不能把RECORD类型作为它的属性。  

DECLARE  
    TYPE name_type IS RECORD                                  -->定义记录类型   
    (  
          first_name    VARCHAR2( 15 )  
        ,last_name      VARCHAR2( 20 )  
    );  
 
    TYPE person_info_type IS RECORD                    -->定义记录类型   
    (  
          id                  NUMBER( 6 )  
        ,name              name_type                                  -->name的类型为name_type,即嵌套     
        ,job_title    jobs.job_title%TYPE  
    );  
 
    person_rec    person_info_type;                      -->声明记录变量   
BEGIN  
    SELECT employee_id  
                ,first_name  
                ,last_name  
                ,job_title  
    INTO    person_rec.id  
                ,person_rec.name.first_name      -->注意此时嵌套记录中的引用方法   
                ,person_rec.name.last_name        -->enclosing_record.(nested_record或者nested_collection).field_name   
                ,person_rec.job_title  
    FROM    employees e JOIN jobs j ON e.job_id = j.job_id AND ROWNUM < 2;  
 
    DBMS_OUTPUT.put_line( 'First name is ' || person_rec.name.first_name );  
    DBMS_OUTPUT.put_line( 'Last name is ' || person_rec.name.last_name );  
END;  
 
6、记录集合  

所有基于记录的集合在此统统可以称之为记录集合,即该集合类型是基于记录类型之上的。  

--下面的示例是一个使用了基于游标类型的联合数组的记录集合   
DECLARE  
    CURSOR cur_emp IS                                              -->声明一个游标   
          SELECT empno, ename, hiredate  
          FROM    emp  
          WHERE  deptno = 20  
          ORDER BY 1;  
 
    TYPE emp_tab_type IS TABLE OF cur_emp%ROWTYPE      -->基于游标类型定义了一个联合数组   
                                                    INDEX BY BINARY_INTEGER;  
 
    emp_tab        emp_tab_type;                              -->声明复合变量   
    v_counter    INTEGER := 0;  
BEGIN  
    FOR emp_rec IN cur_emp  
    LOOP  
          v_counter    := v_counter 1;              -->v_counter用于控制下标       
          emp_tab( v_counter ).empno := emp_rec.empno;    -->给复合变量赋值,注意引用方法   
          emp_tab( v_counter ).ename := emp_rec.ename;  
          emp_tab( v_counter ).hiredate := emp_rec.hiredate;  
          DBMS_OUTPUT.put_line('Recored '||v_counter||' is '||emp_tab(v_counter).ename|| ',' || emp_tab( v_counter ).hiredate );  
    END LOOP;  
END;  
 
--下面的示例是一个基于自定义记录类型的嵌条表,注意嵌套表需要扩展   
--我们知道,游标通常为单条多列的记录,而联合数组,嵌套表以及变长数组为单列多行   
--因此记录类型与集合类型的复合我们可以将其想象成一张二维表,因此对于这种类型的操作,更高效的是直接使用bulk collect子句来操纵   
--下面不再列出使用bulk collect 的示例,注,使用bulk collect子句使集合类型不需要手动扩展   
DECLARE  
    TYPE rec_type IS RECORD                                          -->定义记录类型   
    (  
          ename          emp.ename%TYPE  
        ,empno          emp.empno%TYPE  
        ,hiredate    emp.hiredate%TYPE  
    );  
 
    TYPE emp_tab_type IS TABLE OF rec_type;          -->定义基于记录类型的嵌套表             
 
    emp_tab        emp_tab_type := emp_tab_type( ); -->初始化嵌套表   
    v_counter    INTEGER := 0;  
BEGIN  
    FOR emp_rec IN (SELECT *  
                                    FROM    emp  
                                    WHERE  deptno = 20 )  
    LOOP  
          v_counter    := v_counter 1;  
          emp_tab.EXTEND;                                                    -->需要使用extend方式来扩展     
          emp_tab( v_counter ).empno := emp_rec.empno;  
          emp_tab( v_counter ).ename := emp_rec.ename;  
          emp_tab( v_counter ).hiredate := emp_rec.hiredate;  
          DBMS_OUTPUT.put_line('Recored '||v_counter||' is '||emp_tab(v_counter).ename||','||emp_tab( v_counter ).hiredate );  
    END LOOP;  
END;  


7、几点注意事项:  

a、不能测试记录是否为NULL、是否相等或不等,下面的操作都是非法的。  
              IF dept_rec IS NULL THEN ...  
              IF dept_rec1 = dept_rec2 THEN ...  
 
b、记录类型不同于变长数组与嵌套表,不能存储在数据库中 

---->Author : Robinson Cheng
---->Blog : http://blog.csdn.net/robinson_0612   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值