• 八、PL/SQL 记录



    前言

    记录是一个复合的数据结构,能够把各种相关的数据合并为一个逻辑单元。
    PL/SQL支持三种记录类型:

    • 基于表的记录
    • 基于游标的记录
    • 用户定义的记录

    一、记录类型

    记录结构有点类似于数据库表的一行数据。每个数据项都存储在具有自己的名称和数据类型的字段中。

    1.1 基于表和基于游标的记录

    使用%ROWTYPE属性,可以创建基于表和基于游标的记录。这个属性类似于用定义标量变量的%TYPE属性。

    下例基于表的记录

    DECLARE
        -- ooag_rec记录与ooag_t表中数据行相同的结构。
        ooag_rec ooag_t%ROWTYPE;
    BEGIN
        SELECT *
          INTO ooag_rec
          FROM ooag_t
         WHERE ooagent = 70
           AND rownum = 1;
        -- 如何使用记录中的数据
        DBMS_OUTPUT.PUT_LINE(ooag_rec.ooag011);
    END;
    

    下例基于游标的记录

    DECLARE
        CURSOR ooag_cur IS
            SELECT ooag001,ooag011
              FROM ooag_t
              WHERE ooagent = 70;
        -- 这个记录的结构和游标返回的数据行具有相同的结构
        ooag_rc ooag_cur%ROWTYPE;
    BEGIN
        FOR ooag_rc IN ooag_cur LOOP
            DBMS_OUTPUT.PUT_LINE(ooag_rc.ooag001||','||ooag_rc.ooag011);
        END LOOP;
    END;
       
    

    1.2 用户自定义的记录

    语法:
    TYPE type_name IS RECORD
    (field_name1 datatype1 [NOT NULL] [ := DEFAULT EXPRESSION],
    field_name2 datatype2 [NOT NULL] [ := DEFAULT EXPRESSION],

    field_name3 datatype3 [NOT NULL] [ := DEFAULT EXPRESSION]);

    NOT NULL表示NOT NULL约束。

    DECLARE
        TYPE time_rec_type IS RECORD
        (cur_date DATE,
         cur_day VARCHAR2(12),
         cur_time VARCHAR2(8) := '00:00:00');
        time_rec time_rec_type;
    BEGIN
        SELECT sysdate
          INTO time_rec.cur_date
          FROM dual;
        time_rec.cur_day := TO_CHAR(time_rec.cur_date, 'DAY');
        time_rec.cur_time := TO_CHAR(time_rec.cur_date, 'HH24:MI:SS');
        
        DBMS_OUTPUT.PUT_LINE('Date: '||TO_CHAR(time_rec.cur_date,'yyyy/mm/dd'));
        DBMS_OUTPUT.PUT_LINE('Day: '||time_rec.cur_day);
        DBMS_OUTPUT.PUT_LINE('Time: '||time_rec.cur_time);
    END;
    

    上例执行结果如下:

    Date: 2022/09/29
    Day: 星期四
    Time: 09:24:21
    

    当声明记录类型时,如果为单个字段指定NOT NULL约束,必须初始化这种字段。

    DECLARE
       TYPE rec_type IS RECORD
       (field1 VARCHAR2(255),
        field2 VARCHAR2(100) NOT NULL = 'hello,world!');
       rec_var rec_type;
    BEGIN
       ......
    END;
    

    1.3 记录的兼容性

    类型不同的记录不能直接赋值。

    DECLARE
        TYPE name_type1 IS RECORD
        (name varchar2(100));
        TYPE name_type2 IS RECORD
        (name varchar2(100));
        name_rec1 name_type1;
        name_rec2 name_type2;
    BEGIN
        name_rec1.name = '张三';
        name_rec2.name = '王五';
        -- 这样直接给记录赋值就报错
        name_rec1 = name_rec2;
        -- 需要这样做
        name_rec1.name = name_rec2.name;
    END;
    

    1.4 嵌套记录

    DECLARE
        TYPE name_type IS RECORD
        (first_name varchar2(50),
         last_name varchar2(50));
        TYPE person_type IS RECORD
        -- 记录中又有一个记录类型name_type
        (name name_type,
         street varchar2(50),
         city varchar2(25));
         person_rec person_type;
        ............
        -- 使用 person_rc.name.first_name
    

    1.5 记录的集合

    1.5.1 使用索引表

    DECLARE
        CURSOR ooag_cur IS
            SELECT ooag001,ooag011
              FROM ooag_t
             WHERE ooagent = 70;
        -- 这个索引表就相当于记录的集合
        TYPE ooag_type IS TABLE OF ooag_cur%ROWTYPE
        INDEX BY BINARY_INTEGER;
        ooag_tab ooag_type;
        v_cnt INTEGER := 0;
    BEGIN
        FOR ooag_rec IN ooag_cur LOOP
            v_cnt := v_cnt + 1;
            -- 将ooag_tab这个索引表填上数据
            ooag_tab(v_cnt).ooag001 := ooag_rec.ooag001;
            ooag_tab(v_cnt).ooag011 := ooag_rec.ooag011;
        END LOOP;
        FOR i in 1..ooag_tab.count() LOOP
            DBMS_OUTPUT.PUT_LINE(ooag_tab(i).ooag001||':'||ooag_tab(i).ooag011);
        END LOOP;
    END;
    

    1.5.2 使用嵌套表

    DECLARE
        CURSOR ooag_cur IS
            SELECT ooag001,ooag011
              FROM ooag_t
             WHERE ooagent = 70;
        -- 这个嵌套表就相当于记录的集合
        TYPE ooag_type IS TABLE OF ooag_cur%ROWTYPE;
        -- 嵌套表不索引关键字,必须初始化
        ooag_tab ooag_type := ooag_type();
        v_cnt INTEGER := 0;
    BEGIN
        FOR ooag_rec IN ooag_cur LOOP
            v_cnt := v_cnt + 1;
            -- 用一个扩展一个
            ooag_tab.EXTEND;
            -- 将ooag_tab这个索引表填上数据
            ooag_tab(v_cnt).ooag001 := ooag_rec.ooag001;
            ooag_tab(v_cnt).ooag011 := ooag_rec.ooag011;
        END LOOP;
        FOR i in 1..ooag_tab.count() LOOP
            DBMS_OUTPUT.PUT_LINE(ooag_tab(i).ooag001||':'||ooag_tab(i).ooag011);
        END LOOP;
    END;
    
  • 相关阅读:
    `算法知识` 裴蜀定理Bezout
    【go语言开发】gorm库连接和操作mysql,实现一个简单的用户注册和登录
    小白备战大厂算法笔试(六)——堆
    multisim仿真电路图红绿灯
    旅游景区IP网络广播系统方案-旅游风景区景点IP网络广播建设指南
    05-LoadBalancer负载均衡
    第十届IEEE电气工程与自动化国际学术论坛(IFEEA 2023)
    鸿蒙tabbar ArkTS
    Java.lang.Class类 getCanonicalName方法有什么功能呢?
    NVIDIA Jetson Xavier CAN 开机启动及应用编程
  • 原文地址:https://blog.csdn.net/weixin_42710036/article/details/127100099