OraclePL/SQL数据类型增强--集合
程序员文章站
2022-09-28 14:35:17
OraclePL/SQL数据类型增强--集合。Oracle 没有数组的概念 ,Oracle有两种类型的集合, 两种集合数据类型:嵌套表和varray。其中varray集合中的元素是...
OraclePL/SQL数据类型增强--集合。Oracle 没有数组的概念 ,Oracle有两种类型的集合, 两种集合数据类型:嵌套表和varray。其中varray集合中的元素是有数量限制的,index_by表和嵌套表是没有这个限制的。index-by表是稀疏的,也就是说下标可以不连续,varray类型的集合则是紧密的,他的下标没有间隔。index_by表不能存储在数据库中,但是嵌套表和varray可以被存储在数据库中。 集合在使用时必须先使用type进行定义方可使用。
可变数组(PL/SQL内存表)
PL/SQL内存表即 Index By Table , 这种结构类似于数组,使用主键提供类似于数组那样的元素访问。 这种类型必须包括两部分:1、使用 BINARY_INTEGER 类型构成的索引主键; 2、另外一个简单类型或者用户自定义类型的字段作为具体的数组元素。这种类型可以自动增长,所以也类似于可变长数组。
定义语法: TYPE type_name IS TABLE OF {column_type | variable%TYPE | table.column%TYPE} [NOT NULL] | table.%ROWTYPE } [INDEX BY BINARY_INTEGER]; identifier type_name; -- 一维数组 DECLARE TYPE t_table IS TABLE OF VARCHAR2(3) INDEX BY BINARY_INTEGER; -- TYPE 集合的变量类型名称 is table of 集合中存储的元素的变量类型 index by 集合索引的下标的变量类型 -- 这里定义了一个可变的数组,数组中存储的是最大为三个字符的字符串,数组通过整数来作为索引下表 v_table t_table; -- 用定义的变量类型的名称来定义变量实体 v_cnt NUMBER; BEGIN v_table(1) := '111'; v_table(2) := '333'; v_table(3) := '999';
v_cnt := v_table.COUNT; -- 获取数组的实际元素个数 FOR i IN 1 .. v_cnt LOOP dbms_output.put_line(v_table(i)); END LOOP; END;
-- 多维数组,这时候数组存储的元素的类型,不是Oracle中已经预定义好的 number,varchar2,date 等类型。而是我们用 type record 定义的记录类型 DECLARE
TYPE t_record_user IS RECORD( -- 定义一个新的记录类型 里面存储一个数字值,一个字符串值 user_id fnd_user.user_id%type, user_name fnd_user.user_name%type);
TYPE t_user IS TABLE OF t_record_user INDEX BY BINARY_INTEGER; -- 定义可变集合的时候指定他的变量类型,索引下标任然使用整数 v_arry_user t_user; --定义集合类型的变量实体
BEGIN SELECT user_id, user_name BULK COLLECT INTO v_arry_user FROM fnd_user; -- 将查询结果一次性放到集合中去,而不是通过cursor一条一条执行 FOR i IN 1 .. v_arry_user.COUNT LOOP dbms_output.put_line(v_arry_user(i).user_name); END LOOP; END;
集合的常用属性和方法
COUNT 返回集合中元素的个数
DELETE 删除集合中所有元素
DELETE(x) 删除元素下标为x的元素,如果x为null,则集合保持不变 对VARRAY非法
DELETE(x,y) 删除元素下标从X到Y的元素,如果X>Y集合保持不变 对VARRAY非法
EXIST(x) 如果集合元素x已经初始化,则返回TRUE, 否则返回FALSE
EXTEND 在集合末尾添加一个元素 对Index_by非法
EXTEND(x) 在集合末尾添加x个元素 对Index_by非法
EXTEND(x,n) 在集合末尾添加元素n的x个副本 对Index_by非法
FIRST 返回集合中的第一个元素的下标号,对于VARRAY集合始终返回1。
LAST 返回集合中最后一个元素的下标号, 对于VARRAY返回值始终等于COUNT。
LIMIT 返回VARRY集合的最大的元素个数,对于嵌套表和Index_by集合无用。
NEXT(x) 返回在元素x之后及紧挨着它的元素的值,如果该元素是最后一个元素,则返回null。
PRIOR(x) 返回集合中在元素x之前紧挨着它的元素的值,如果该元素是第一个元素,则返回null。
TRIM 从集合末端开始删除一个元素 对index_by不合法
TRIM(x) 从集合末端开始删除x个元素 对index_by不合法
嵌套表
上面我们介绍了内存表,其实嵌套表是特殊的内存表(也有人称为索引表),定义的时候没有指定他的索引下标。嵌套表就相当于是一个值集,你可以认为嵌套表就是一个没有定义元素数量的一维数 组,当然你可以通过将嵌套表作为元素来创建嵌套表,这样就可以创建多维数组了。 嵌套表也是存储在内存中的,需要使用构造函数来初始化嵌套表 嵌套表不支持以下的数据类型:BOOLEAN, NCHAR,NCLOB,NVARCAHR2,REF CURSOR,TABLE,VARRAY,NOT NULL。 嵌套表和索引表中有个很重要的区别就是嵌套表中的索引必须是连续的(没有定义索引),不能像索引 表中的那样随意变换的。 在嵌套表中可以使用的函数如下表所示,重点关注的是 EXTEND函数,用于在嵌套表 的后面添加条目。
DECLARE CURSOR c_student IS SELECT * FROM mychu_student WHERE 1 = 1;
TYPE student_tbl_type IS TABLE OF mychu_student%ROWTYPE;
l_student_tbl student_tbl_type; i NUMBER := 0; BEGIN
--初始化嵌套表 l_student_tbl := student_tbl_type(); -- 可以理解为用构造函数创建一个嵌套表对象
FOR student_rec IN c_student LOOP i := i + 1; l_student_tbl.EXTEND(1); -- 在集合末尾添加一个元素 l_student_tbl(i) := student_rec; END LOOP;
l_student_tbl.EXTEND(2, 2); -- 在集合末尾添加两个元素,元素的值从集合第二个值复制过去
FOR i IN 1 .. l_student_tbl.COUNT LOOP dbms_output.put_line(l_student_tbl(i) .sname || ' ' || l_student_tbl(i).sage); END LOOP;
--从集合的尾部删除两个元素 l_student_tbl.TRIM(2);
dbms_output.put_line('table count: ' || l_student_tbl.COUNT);
FOR i IN 1 .. l_student_tbl.COUNT LOOP dbms_output.put_line(l_student_tbl(i) .sname || ' ' || l_student_tbl(i).sage); END LOOP;
--删除所有元素 l_student_tbl.DELETE;
END;
Oracle集合一般可以分为固定数组和可变数组
集合:是具有相同定义的元素的聚合。Oracle有两种类型的集合:
可变长数组(VARRAY):可以有任意数量的元素,但必须预先定义限制值。
嵌套表:视为表中之表,可以有任意数量的元素,不需要预先定义限制值。
固定数组 declare type arry_var is varray(2) of varchar2(10); -- 这个类型的集合能够存储两个元素值,元素值类型是字符串类型,每个元素值得大小控制在十个字符范围内 -- type 集合的变量类型名称 is varray(集合元素的个数) of 集合中元素的变量类型 arry_name arry_var; begin arry_name := arry_var('tom', 'jim'); dbms_output.put_line(arry_name(1)); dbms_output.put_line(arry_name(2)); end;可变数组(PL/SQL内存表)
PL/SQL内存表即 Index By Table , 这种结构类似于数组,使用主键提供类似于数组那样的元素访问。 这种类型必须包括两部分:1、使用 BINARY_INTEGER 类型构成的索引主键; 2、另外一个简单类型或者用户自定义类型的字段作为具体的数组元素。这种类型可以自动增长,所以也类似于可变长数组。
定义语法: TYPE type_name IS TABLE OF {column_type | variable%TYPE | table.column%TYPE} [NOT NULL] | table.%ROWTYPE } [INDEX BY BINARY_INTEGER]; identifier type_name; -- 一维数组 DECLARE TYPE t_table IS TABLE OF VARCHAR2(3) INDEX BY BINARY_INTEGER; -- TYPE 集合的变量类型名称 is table of 集合中存储的元素的变量类型 index by 集合索引的下标的变量类型 -- 这里定义了一个可变的数组,数组中存储的是最大为三个字符的字符串,数组通过整数来作为索引下表 v_table t_table; -- 用定义的变量类型的名称来定义变量实体 v_cnt NUMBER; BEGIN v_table(1) := '111'; v_table(2) := '333'; v_table(3) := '999';
v_cnt := v_table.COUNT; -- 获取数组的实际元素个数 FOR i IN 1 .. v_cnt LOOP dbms_output.put_line(v_table(i)); END LOOP; END;
-- 多维数组,这时候数组存储的元素的类型,不是Oracle中已经预定义好的 number,varchar2,date 等类型。而是我们用 type record 定义的记录类型 DECLARE
TYPE t_record_user IS RECORD( -- 定义一个新的记录类型 里面存储一个数字值,一个字符串值 user_id fnd_user.user_id%type, user_name fnd_user.user_name%type);
TYPE t_user IS TABLE OF t_record_user INDEX BY BINARY_INTEGER; -- 定义可变集合的时候指定他的变量类型,索引下标任然使用整数 v_arry_user t_user; --定义集合类型的变量实体
BEGIN SELECT user_id, user_name BULK COLLECT INTO v_arry_user FROM fnd_user; -- 将查询结果一次性放到集合中去,而不是通过cursor一条一条执行 FOR i IN 1 .. v_arry_user.COUNT LOOP dbms_output.put_line(v_arry_user(i).user_name); END LOOP; END;
集合的常用属性和方法
COUNT 返回集合中元素的个数
DELETE 删除集合中所有元素
DELETE(x) 删除元素下标为x的元素,如果x为null,则集合保持不变 对VARRAY非法
DELETE(x,y) 删除元素下标从X到Y的元素,如果X>Y集合保持不变 对VARRAY非法
EXIST(x) 如果集合元素x已经初始化,则返回TRUE, 否则返回FALSE
EXTEND 在集合末尾添加一个元素 对Index_by非法
EXTEND(x) 在集合末尾添加x个元素 对Index_by非法
EXTEND(x,n) 在集合末尾添加元素n的x个副本 对Index_by非法
FIRST 返回集合中的第一个元素的下标号,对于VARRAY集合始终返回1。
LAST 返回集合中最后一个元素的下标号, 对于VARRAY返回值始终等于COUNT。
LIMIT 返回VARRY集合的最大的元素个数,对于嵌套表和Index_by集合无用。
NEXT(x) 返回在元素x之后及紧挨着它的元素的值,如果该元素是最后一个元素,则返回null。
PRIOR(x) 返回集合中在元素x之前紧挨着它的元素的值,如果该元素是第一个元素,则返回null。
TRIM 从集合末端开始删除一个元素 对index_by不合法
TRIM(x) 从集合末端开始删除x个元素 对index_by不合法
嵌套表
上面我们介绍了内存表,其实嵌套表是特殊的内存表(也有人称为索引表),定义的时候没有指定他的索引下标。嵌套表就相当于是一个值集,你可以认为嵌套表就是一个没有定义元素数量的一维数 组,当然你可以通过将嵌套表作为元素来创建嵌套表,这样就可以创建多维数组了。 嵌套表也是存储在内存中的,需要使用构造函数来初始化嵌套表 嵌套表不支持以下的数据类型:BOOLEAN, NCHAR,NCLOB,NVARCAHR2,REF CURSOR,TABLE,VARRAY,NOT NULL。 嵌套表和索引表中有个很重要的区别就是嵌套表中的索引必须是连续的(没有定义索引),不能像索引 表中的那样随意变换的。 在嵌套表中可以使用的函数如下表所示,重点关注的是 EXTEND函数,用于在嵌套表 的后面添加条目。
DECLARE CURSOR c_student IS SELECT * FROM mychu_student WHERE 1 = 1;
TYPE student_tbl_type IS TABLE OF mychu_student%ROWTYPE;
l_student_tbl student_tbl_type; i NUMBER := 0; BEGIN
--初始化嵌套表 l_student_tbl := student_tbl_type(); -- 可以理解为用构造函数创建一个嵌套表对象
FOR student_rec IN c_student LOOP i := i + 1; l_student_tbl.EXTEND(1); -- 在集合末尾添加一个元素 l_student_tbl(i) := student_rec; END LOOP;
l_student_tbl.EXTEND(2, 2); -- 在集合末尾添加两个元素,元素的值从集合第二个值复制过去
FOR i IN 1 .. l_student_tbl.COUNT LOOP dbms_output.put_line(l_student_tbl(i) .sname || ' ' || l_student_tbl(i).sage); END LOOP;
--从集合的尾部删除两个元素 l_student_tbl.TRIM(2);
dbms_output.put_line('table count: ' || l_student_tbl.COUNT);
FOR i IN 1 .. l_student_tbl.COUNT LOOP dbms_output.put_line(l_student_tbl(i) .sname || ' ' || l_student_tbl(i).sage); END LOOP;
--删除所有元素 l_student_tbl.DELETE;
END;
上一篇: C语言算法训练 安慰奶牛