除了基本数据类型,Oracle中提供了一种自定义数据类型的方法,类似C语言中的结构类型。
TYPE <数据类型名称> IS <数据类型>;
在Oracle中用户被允许定义两种类型,RECORD类型(记录类型)和TABLE类型(表类型)。
-- 定义一个交易记录类型
TYPE TRANS_RECORD IS RECORD (
FEE NUMBER, -- 定义交易金额
TRANS_TIME DATE -- 定义交易时间
);
通过TYPE定义了一个记录类型TRANS_RECORD,其中该记录中包含两个值FEE和TRANS_TIME。然后可以使用该类型去定义变量。例如:
V_TRANS_RECORD TRANS_RECORD;
如此就可以通过赋值为变量V_TRANS_RECORD中的两个变量进行赋值和调用。
-- 赋值
V_TRANS_RECORD.FEE = 3000;
V_TRANS_RECORD.TRANS_TIME = SYSDATE();
-- 调用
DBMS_OUTPUT.PUT_LINE(V_TRANS_RECORD.FEE);
DBMS_OUTPUT.PUT_LINE(TO_CHAR(V_TRANS_RECORD.TRANS_TIME, 'YYYY-MM-DD'));
-- 定义单列的TABLE类型
DECLARE
TYPE TYPE_TRANS_FEE_RECORD IS TABLE OF NUMBER(2) INDEX BY BINARY_INTEGER;
V_TRANS_FEE_RECORD TYPE_TRANS_FEE_RECORD;
i NUMBER := 1;
BEGIN
-- 为变量赋值
V_TRANS_FEE_RECORD(1) := 1;
V_TRANS_FEE_RECORD(2) := 2;
V_TRANS_FEE_RECORD(3) := 3;
V_TRANS_FEE_RECORD(4) := 4;
-- 输出变量
WHILE i <= V_TRANS_FEE_RECORD.LAST LOOP
DBMS_OUTPUT.PUT_LINE(V_TRANS_FEE_RECORD(i));
i := i + 1;
END LOOP;
END;
通过%ROWTYPE定义多行多列的数据集合
-- 定义数据表
CREATE TABLE TB_TRANS_RECORD (FEE NUMBER, TRANS_TIME DATE);
INSERT INTO TB_TRANS_RECORD VALUES(3000, TO_DATE('2020-08-01', 'YYYY-MM-DD'));
INSERT INTO TB_TRANS_RECORD VALUES(4000, TO_DATE('2020-08-02', 'YYYY-MM-DD'));
-- 定义多行多列的数据类型
DECLARE
TYPE TYPE_TRANS_RECORD IS TABLE OF TB_TRANS_RECORD%ROWTYPE;
V_TRANS_RECORD TYPE_TRANS_RECORD;
i NUMBER := 1;
BEGIN
-- 采用bulkcollect可以将查询结果一次性地加载到collections中
SELECT FEE, TRANS_TIME BULK COLLECT INTO V_TRANS_RECORD FROM TB_TRANS_RECORD;
-- 循环输出集合结果
WHILE i <= V_TRANS_RECORD.LAST LOOP
DBMS_OUTPUT.PUT_LINE(V_TRANS_RECORD(i).FEE || ',' || TO_CHAR(V_TRANS_RECORD(i).TRANS_TIME, 'YYYY-MM-DD'));
i := i + 1;
END LOOP;
END;
通过RECORD定义多行多列的数据集合
-- 定义数据表
CREATE TABLE TB_TRANS_RECORD (FEE NUMBER, TRANS_TIME DATE);
INSERT INTO TB_TRANS_RECORD VALUES(3000, TO_DATE('2020-08-01', 'YYYY-MM-DD'));
INSERT INTO TB_TRANS_RECORD VALUES(4000, TO_DATE('2020-08-02', 'YYYY-MM-DD'));
DECLARE
TYPE TRANS_RECORD IS RECORD (
FEE TB_TRANS_RECORD.FEE%TYPE,
TRANS_TIME TB_TRANS_RECORD.TRANS_TIME%TYPE
);
TYPE TYPE_TRANS_RECORD IS TABLE OF TRANS_RECORD;
V_TRANS_RECORD TYPE_TRANS_RECORD;
i NUMBER := 1;
BEGIN
-- 采用bulkcollect可以将查询结果一次性地加载到collections中
SELECT FEE, TRANS_TIME BULK COLLECT INTO V_TRANS_RECORD FROM TB_TRANS_RECORD;
-- 循环输出集合结果
WHILE i <= V_TRANS_RECORD.LAST LOOP
DBMS_OUTPUT.PUT_LINE(V_TRANS_RECORD(i).FEE || ',' || TO_CHAR(V_TRANS_RECORD(i).TRANS_TIME, 'YYYY-MM-DD'));
i := i + 1;
END LOOP;
END;
处理TYPE可以自定义类型,PL/SQL还提供了%TYPE和%ROWTYPE两种特殊的变量,用于声明与表的列相匹配的变量和用户定义数据类型,前一个表示单属性的数据类型,后一个表示整个属性列表的结构,即元组的类型。例如:
-- 数据表TB_TRANS_RECORD
CREATE TABLE TB_TRANS_RECORD (
FEE NUMBER,
TRANS_TIME DATE
)
-- 定义一个与表TB_TRANS_RECORD中FEE类型相同的变量
DECLARE
FEE TB_TRANS_RECORD.FEE%TYPE;
-- 定义一个与表TB_TRANS_RECORD结构相同的数组
DECLARE
V_TB_TRANS_RECORD TB_TRANS_RECORD%ROWTYPE;
-- 为数组中的变量赋值
BEGIN
V_TB_TRANS_RECORD.FEE := 2000;
V_TB_TRANS_RECORD.TRANS_TIME := SYSDATE();
END;
通过%TYPE和%ROWTYPE定义出来的变量会随着原数据表的结构的变化而变化,进而避免了我们在修改表字段类型时对其他程序中定义的变量造成的影响。
CREATE OR REPLACE TYPE <类型名称> AS OBJECT (
<字段名> <字段类型>,
[...]
);
-- 创建对象
CREATE OR REPLACE TYPE O_TRANS_RECORD AS OBJECT (
FEE NUMBER,
TRANS_TIME DATE
);
/
-- 创建变量
DECLARE
V_TRANS_RECORD O_TRANS_RECORD;
BEGIN
V_TRANS_RECORD := O_TRANS_RECORD(3000, SYSDATE());
DBMS_OUTPUT.PUT_LINE(V_TRANS_RECORD.FEE);
DBMS_OUTPUT.PUT_LINE(TO_CHAR(V_TRANS_RECORD.TRANS_TIME, 'YYYY-MM-DD'));
END;
创建对象的方法与TYPE定义类型类似,创建类型在类型后使用AS
,TYPE则使用IS
;TYPE创建的类型包含OBJECT类和TABLE类,TYPE定义的是RECORD类型;TYPE创建的语句是独立的,而TYPE定义的语句需要写在代码块中。