• 记录


    记录由单行多列的标量构成,是一种复合数据结构。

    PL/SQL支持三种记录类型:基于表的记录、基于游标的记录以及用户自定义的记录。

    一、 基于表的记录

    DECLARE
       emp_rec emp%rowtype;
    BEGIN
       SELECT * INTO emp_rec FROM emp WHERE empno=7788;
    DBMS_OUTPUT.PUT_LINE(
    'Ename is: '||emp_rec.ename); DBMS_OUTPUT.PUT_LINE('Job is: '||emp_rec.job); DBMS_OUTPUT.PUT_LINE('Salary is: '||emp_rec.sal); END;

    二、 基于游标的记录

    DECLARE
      CURSOR emp_cur IS SELECT * FROM emp WHERE rownum <=4;
      emp_rec emp_cur%ROWTYPE;
    BEGIN
      OPEN emp_cur;
      LOOP
         FETCH emp_cur INTO emp_rec;
         EXIT WHEN emp_cur%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE(
    'Ename is: '||emp_rec.ename); DBMS_OUTPUT.PUT_LINE('Job is: '||emp_rec.job); DBMS_OUTPUT.PUT_LINE('Salary is: '||emp_rec.sal); END LOOP; END;

    三、 用户自定义的记录

    创建用户自定义记录的语法如下所示:

    TYPE type_name IS RECORD
       (field_name1 datatype1 [NOT NULL] [ := DEFAULT EXPRESSION],
        field_name2 datatype2 [NOT NULL] [ := DEFAULT EXPRESSION],
        ...
        field_nameN datatypeN [NOT NULL] [ := DEFAULT EXPRESSION]);
    record_name TYPE_NAME;

    试举一例:

    DECLARE
      TYPE time_rec_type IS RECORD
         (curr_date DATE,
          curr_day  VARCHAR2(12),
          curr_time VARCHAR(8) :='00:00:00'
          );   
      time_rec TIME_REC_TYPE;
    BEGIN
      SELECT sysdate INTO time_rec.curr_date FROM dual;
      time_rec.curr_day := TO_CHAR(time_rec.curr_date,'DAY');
      time_rec.curr_time := TO_CHAR(time_rec.curr_date,'HH24:MI:SS');
     
    DBMS_OUTPUT.PUT_LINE(
    'Date: '||time_rec.curr_date); DBMS_OUTPUT.PUT_LINE('Day: '||time_rec.curr_day); DBMS_OUTPUT.PUT_LINE('Time: '||time_rec.curr_time); END;

    注意:

    1> 当声明记录类型时,如果为某个字段指定了NOT NULL约束,则必须初始化该字段。譬如上例中,如果字段curr_date指定了NOT NULL约束,即curr_date DATE NOT NULL,则会报如下错误:PLS-00218: a variable declared NOT NULL must have an initialization assignment。可初始化为:curr_date DATE NOT NULL :=sysdate。

    2> 记录不可以整体判断为空,只可以判断记录字段。

    3> 记录不可以整体比较,只可以比较记录字段。

    4> 可以把基于表或者游标的记录整体赋值给用户自定义的记录,只要两者具有相同的结构。但对于用户自定义的记录来说,即便两个自定义记录具有相同的结构,但类型却不同,不可整体赋值。如下所示:

    DECLARE
      TYPE name_type1 IS RECORD
         (first_name VARCHAR2(15),
          last_name  VARCHAR2(30)
          );
      TYPE name_type2 IS RECORD
         (first_name VARCHAR2(15),
          last_name  VARCHAR2(15)
          );
       name_rec1 name_type1;
       name_rec2 name_type2;
    BEGIN
       name_rec1.first_name := 'John';
       name_rec1.last_name := 'Smith';
       name_rec2 := name_rec1;
    END;

    运行报如下错误:

    SQL> /
    name_rec2 := name_rec1;
    *
    ERROR at line 15:
    ORA-06550: line 15, column 17:
    PLS-00382: expression is of wrong type
    ORA-06550: line 15, column 4:
    PL/SQL: Statement ignored

    可见,两个记录虽然拥有相同的结构,但,每个记录的类型不同,该记录也是不兼容的,整体赋值就会报错。

    上例可修改为:

    DECLARE
      TYPE name_type1 IS RECORD
         (first_name VARCHAR2(15),
          last_name  VARCHAR2(30)
          );
       name_rec1 name_type1;
       name_rec2 name_type1;
    BEGIN
       name_rec1.first_name := 'John';
       name_rec1.last_name := 'Smith';
       name_rec2 := name_rec1;
    END;

     上述整体赋值的限制只局限于用户自定义记录类型。可以把基于表或者游标的记录整体赋值给用户自定义的记录,只要两者具有相同的结构。

    DECLARE
      CURSOR dept_cur IS SELECT * FROM dept;
      TYPE dept_type IS RECORD
         (deptno dept.deptno%TYPE,
          dname  dept.dname%TYPE,
          loc    dept.loc%TYPE
          );
       dept_rec1 dept%ROWTYPE;   -- table-based record
       dept_rec2 dept_cur%ROWTYPE; -- cursor-based record
       dept_rec3 dept_type;
    BEGIN
       -- Populate table-based record
       SELECT * INTO dept_rec1 FROM dept WHERE deptno=10;
       dept_rec2 := dept_rec1; 
       dept_rec3 := dept_rec1; 
     
       --Populate cursor-based record 
       OPEN dept_cur;
       LOOP
          FETCH dept_cur INTO dept_rec2;
          EXIT WHEN dept_cur%NOTFOUND;
       END LOOP;
       dept_rec1 := dept_rec2;
       dept_rec3 := dept_rec2;
       
       --Populate user defined record
       SELECT * INTO dept_rec3 FROM dept WHERE deptno=20;
       dept_rec1 := dept_rec3;
       dept_rec2 := dept_rec3;
    END;

    四、 嵌套记录

    嵌套记录指的记录中包含其他记录和集合。

    譬如:

    DECLARE
      TYPE name_type IS RECORD
          (first_name  VARCHAR2(15);
           last_name   VARCHAR2(30));
      TYPE person_type IS RECORD
          (name   name_type;  
           street VARCHAR2(50);
           city   VARCHAR2(25);
           state  VARCHAR2(2);
           zip    VARCHAR2(5)); 
      person_rec person_type;
                         

    这段代码包含两个用户自定义记录类型,其中,第二个用户自定义记录类型person_type是个嵌套的记录类型,因为其字段name是name_type类型的记录。

    综合示例:

    一、 输入部门号,输出该部门的员工

    DECLARE
      TYPE ename_type IS TABLE OF emp.ename%TYPE INDEX BY BINARY_INTEGER;
      
      TYPE dept_info_type IS RECORD
          (deptno    emp.deptno%TYPE,
           ename_tab ename_type);
      
      CURSOR name_cur (p_deptno number) IS
         SELECT ename
           FROM emp
         WHERE deptno = p_deptno;
      
      dept_info_rec dept_info_type;
      v_deptno  NUMBER(2) := &v_deptno;
      v_counter INTEGER := 0;
    BEGIN
      dept_info_rec.deptno := v_deptno;
      DBMS_OUTPUT.PUT_LINE('Deptno: '||dept_info_rec.deptno||chr(10)||'Employees:');
      
      FOR name_rec IN name_cur(v_deptno) LOOP
         v_counter := v_counter+1;
         dept_info_rec.ename_tab(v_counter) := name_rec.ename;
      END LOOP;
      
      FOR i IN 1..dept_info_rec.ename_tab.COUNT LOOP
          DBMS_OUTPUT.PUT_LINE(dept_info_rec.ename_tab(i));
      END LOOP;
    END;

    输出结果为: 

    Enter value for v_deptno: 10
    old 14: v_deptno NUMBER(2) := &v_deptno;
    new 14: v_deptno NUMBER(2) := 10;
    Deptno: 10
    Employees:
    CLARK
    KING
    MILLER

    PL/SQL procedure successfully completed.

    二、 输出每个部门的员工总数

    DECLARE
      CURSOR dept_cur IS
        SELECT dname,loc,count(*) total
          FROM dept,emp
        WHERE dept.deptno=emp.deptno
        GROUP BY dname,loc;
    
      TYPE dname_rec_type IS RECORD
         (dname dept.dname%TYPE,
          loc   dept.loc%TYPE,
          total INTEGER);
      
      TYPE dept_type IS TABLE OF dname_rec_type INDEX BY BINARY_INTEGER;
      
      dept_tab dept_type;
      v_counter INTEGER :=0;
    BEGIN
      FOR dept_rec IN dept_cur LOOP
         v_counter := v_counter+1;
         
         dept_tab(v_counter).dname := dept_rec.dname;
         dept_tab(v_counter).loc := dept_rec.loc;
         dept_tab(v_counter).total := dept_rec.total;
         
         DBMS_OUTPUT.PUT_LINE(dept_tab(v_counter).dname||' '||dept_tab(v_counter).loc
             ||' '||dept_tab(v_counter).total);
      END LOOP;
    END;

    输出结果为:

    RESEARCH DALLAS 5
    SALES CHICAGO 7
    ACCOUNTING NEW YORK 3

    PL/SQL procedure successfully completed.

  • 相关阅读:
    Selenium环境搭建
    系统测试用例评审checklist
    软件测试入门
    App测试方法总结
    好东西并查集
    自己编写一个数组去掉重复元素的函数
    杭电OJ BestCoder28期1001Missing number问题(小技巧偏移法)
    介绍一个二次排序的小技巧(best coder27期1001jump jump jump)
    ntohs的一个简单实现(将网络流中用两个字节16进制表示的资源数(如DNS)和长度转换为整形)
    一个节省空间的小技巧
  • 原文地址:https://www.cnblogs.com/ivictor/p/3949369.html
Copyright © 2020-2023  润新知