PL/SQL复合数据类型
--一.PL/SQL复合数据类型 --(一).PL/SQL记录 --1.定义PL/SQL记录 --(1).定义PL/SQL记录 --Grammar TYPE type_name IS RECORD( field_declaration1[, field_declaration2]... ); idetifier type_name; --Demo1 DECLARE TYPE emp_record_type IS RECORD( name emp.ename%TYPE, salary emp.sal%TYPE, dno emp.deptno%TYPE ); emp_record emp_record_type; ... --(2).使用%ROWTYPE属性定义记录变量 --Grammer identifier table_name%ROWTYPE; identifier view_name%ROWTYPE; --Demo1 dept_record dept%ROWTYPE; emp_record emp%ROWTYPE; --2.使用PL/SQL记录 --Demo1:SELECT INTO 中用PL/SQL记录 SQL> SET SERVEROUTPUT ON; SQL> DECLARE 2 TYPE emp_record_type IS RECORD( 3 name emp.ename%TYPE, 4 salary emp.sal%TYPE, 5 dno emp.deptno%TYPE 6 ); 7 emp_record emp_record_type; 8 BEGIN 9 SELECT ename,sal,deptno INTO emp_record 10 FROM emp 11 WHERE empno=&no; 12 dbms_output.put_line(emp_record.name); 13 END; 14 / 输入 no 的值: 7788 原值 11: WHERE empno=&no; 新值 11: WHERE empno=7788; SCOTT PL/SQL 过程已成功完成。 --Demo2:SELECT INTO 中用PL/SQL记录成员变量记录 SQL> SET SERVEROUTPUT ON; SQL> DECLARE 2 TYPE emp_record_type IS RECORD( 3 name emp.ename%TYPE, 4 salary emp.sal%TYPE, 5 dno emp.deptno%TYPE 6 ); 7 emp_record emp_record_type; 8 BEGIN 9 SELECT ename,sal INTO emp_record.name,emp_record.salary 10 FROM emp 11 WHERE empno=&no; 12 dbms_output.put_line(emp_record.name); 13 END; 14 / 输入 no 的值: 7369 原值 11: WHERE empno=&no; 新值 11: WHERE empno=7369; SMITH PL/SQL 过程已成功完成。 --Demo3:INSERT 中用PL/SQL记录 SQL> SET SERVEROUTPUT ON; SQL> DECLARE 2 dept_record dept%ROWTYPE; 3 BEGIN 4 dept_record.deptno:=50; 5 dept_record.dname:='ADMINISTRATOR'; 6 dept_record.loc:='BEIJING'; 7 INSERT INTO dept VALUES dept_record; 8 dbms_output.put_line('新增'||SQL%ROWCOUNT||'行'); 9 END; 10 / 新增1行 PL/SQL 过程已成功完成。 --Demo4:INSERT VALUES 中用PL/SQL记录成员 SQL> SET SERVEROUTPUT ON; SQL> DECLARE 2 dept_record dept%ROWTYPE; 3 BEGIN 4 dept_record.deptno:=60; 5 dept_record.dname:='SALES'; 6 dept_record.loc:='BEIJING'; 7 INSERT INTO dept(deptno,dname) 8 VALUES (dept_record.deptno,dept_record.dname); 9 dbms_output.put_line('新增'||SQL%ROWCOUNT||'行'); 10 END; 11 / 新增1行 PL/SQL 过程已成功完成。 --Demo5:UPDATE SET 中用PL/SQL记录变量 SQL> SET SERVEROUTPUT ON; SQL> DECLARE 2 dept_record dept%ROWTYPE; 3 BEGIN 4 dept_record.deptno:=30; 5 dept_record.dname:='SALES'; 6 dept_record.loc:='SHANGHAI'; 7 UPDATE dept SET ROW=dept_record 8 WHERE deptno=&deptno; 9 dbms_output.put_line('修改'||SQL%ROWCOUNT||'行'); 10 END; 11 / 输入 deptno 的值: 30 原值 8: WHERE deptno=&deptno; 新值 8: WHERE deptno=30; 修改1行 PL/SQL 过程已成功完成。 --Demo6:UPDATE SET 中用PL/SQL记录变量成员 SQL> SET SERVEROUTPUT ON; SQL> DECLARE 2 dept_record dept%ROWTYPE; 3 BEGIN 4 dept_record.loc:='GUANGZHOU'; 5 UPDATE dept SET loc=dept_record.loc 6 WHERE deptno=&deptno; 7 dbms_output.put_line('修改'||SQL%ROWCOUNT||'行'); 8 END; 9 / 输入 deptno 的值: 10 原值 6: WHERE deptno=&deptno; 新值 6: WHERE deptno=10; 修改1行 PL/SQL 过程已成功完成。 --Demo7:DELETE 中用PL/SQL记录成员(只能用成员) SQL> SET SERVEROUTPUT ON; SQL> DECLARE 2 dept_record dept%ROWTYPE; 3 BEGIN 4 dept_record.deptno:=50; 5 DELETE FROM dept WHERE deptno=dept_record.deptno; 6 dbms_output.put_line('删除'||SQL%ROWCOUNT||'行'); 7 END; 8 / 删除1行 PL/SQL 过程已成功完成。 --(二).PL/SQL集合 --单行单列用标量变量 --单行多列用PL/SQL记录 --多行单列用PL/SQL集合 --集合类型包括索引表,嵌套表,变长数组 --1.索引表,也称为PL/SQL表 --特性:索引表下标可以为负数;索引表的元素个数没有限制;索引表只能作为PL/SQL复合数据类型使用;索引表不能作为表列类型使用 --Grammer:key_type可以使用数据类型BINARY_INTEGER,PLS_INTEGER,VARCHAR2 TYPE type_name IS TABLE OF element_type [NOT NULL] INDEX BY key_type; identifier type_name; --Demo1 SQL> SET SERVEROUTPUT ON; SQL> DECLARE 2 TYPE ename_table_type IS TABLE OF emp.ename%TYPE 3 INDEX BY BINARY_INTEGER; 4 ename_table ename_table_type; 5 BEGIN 6 SELECT ename INTO ename_table(-1) 7 FROM emp 8 WHERE empno=&no; 9 dbms_output.put_line('雇员名:'||ename_table(-1)); 10 END; 11 / 输入 no 的值: 7788 原值 8: WHERE empno=&no; 新值 8: WHERE empno=7788; 雇员名:SCOTT PL/SQL 过程已成功完成。 --Demo2 SQL> SET SERVEROUTPUT ON; SQL> DECLARE 2 TYPE area_table_type IS TABLE OF NUMBER 3 NOT NULL INDEX BY VARCHAR(10); 4 area_table area_table_type; 5 BEGIN 6 area_table('北京'):=1; 7 area_table('上海'):=2; 8 area_table('广州'):=3; 9 dbms_output.put_line('第一个元素:'||area_table.first); 10 dbms_output.put_line('第二个元素:'||area_table.last); 11 END; 12 / 第一个元素:北京 第二个元素:上海 PL/SQL 过程已成功完成。 --2.嵌套表 --特性:下标从1开始;元素个数没有限制;数组元素值可以稀疏;可以作为表列的数据类型使用 --Grammer TYPE type_name IS TABLE OF element_type; identifier type_name; --Demo1:SELECT INTO SQL> SET SERVEROUTPUT ON; SQL> DECLARE 2 TYPE ename_table_type IS TABLE OF emp.ename%TYPE; 3 ename_table ename_table_type; 4 BEGIN 5 --构造函数初始化嵌套表变量后才能在PL/SQL中引用 6 ename_table:=ename_table_type('A','A','A'); 7 SELECT ename INTO ename_table(2) 8 FROM emp 9 WHERE empno=&no; 10 dbms_output.put_line('雇员名:'||ename_table(2)); 11 END; 12 / 输入 no 的值: 7788 原值 9: WHERE empno=&no; 新值 9: WHERE empno=7788; 雇员名:SCOTT PL/SQL 过程已成功完成。 --Demo2:表列中使用嵌套表 SQL> CREATE TYPE phone_type IS TABLE OF VARCHAR(20); 2 / 类型已创建。 SQL> CREATE TABLE employes( 2 id NUMBER(4), 3 name VARCHAR2(10), 4 sal NUMBER(6,2), 5 phone phone_type 6 ) 7 --使用嵌套表作为表列的数据类型时,必须要为嵌套表指定专门的存储表 8 NESTED TABLE phone STORE AS phone_table; 表已创建。 --Demo3:在PL/SQL块中为嵌套表列插入数据 SQL> --当定义嵌套表类型时,Oracle自动为该类型生成对应的构造方法。 SQL> --当为嵌套表插入数据时,需要使用嵌套表的构造方法。 SQL> BEGIN 2 INSERT INTO employes VALUES(2,'SMITH',1000, 3 phone_type('020-81181817','13922390000')); 4 dbms_output.put_line('插入'||SQL%ROWCOUNT||'条'); 5 END; 6 / 插入1条 PL/SQL 过程已成功完成。 --Demo4:在PL/SQL块中检索嵌套表列的数据 SQL> DECLARE 2 phone_table phone_type; 3 BEGIN 4 SELECT phone INTO phone_table 5 FROM employes 6 WHERE id=1; 7 FOR i IN 1..phone_table.COUNT LOOP 8 dbms_output.put_line('电话号码:'||phone_table(i)); 9 END LOOP; 10 END; 11 / 电话号码:020-81181818 电话号码:13922390110 PL/SQL 过程已成功完成。 --Demo5:在PL/SQL中更新嵌套表列的数据 SQL> DECLARE 2 phone_table phone_type:=phone_type('020-817191111','13922222222', 3 '030-81111111','13911111111'); 4 BEGIN 5 UPDATE employes SET phone=phone_table 6 WHERE id=1; 7 dbms_output.put_line('更新'||SQL%ROWCOUNT||'条'); 8 END; 9 / 更新1条 PL/SQL 过程已成功完成。 --3.变长数组VARRAY --特性:下标从1开始;可以作为表列的类型使用;有限定义长度数组 --Grammer TYPE type_name IS VARRAY(size_limit) OF element_type [NOT NULL]; identifier type_name; --Demo1:PL/SQL块中使用VARRAY SQL> DECLARE 2 TYPE ename_varray_type IS VARRAY(20) OF emp.ename%TYPE; 3 --PL/SQL块中引用VARRAY类型变量时,必须使用构造方法初始化。 4 ename_varray ename_varray_type:=ename_varray_type('mary'); 5 BEGIN 6 SELECT ename INTO ename_varray(1) FROM emp 7 WHERE empno=&eno; 8 dbms_output.put_line('雇员名:'||ename_varray(1)); 9 END; 10 / 输入 eno 的值: 7788 原值 7: WHERE empno=&eno; 新值 7: WHERE empno=7788; PL/SQL 过程已成功完成。 --Demo2:表列中使用VARRAY SQL> DROP TABLE employes; 表已删除。 SQL> DROP TYPE phone_type; 类型已删除。 SQL> SQL> CREATE TYPE phone_type IS VARRAY(20) OF VARCHAR2(20); 2 / 类型已创建。 SQL> CREATE TABLE employes( 2 id NUMBER(4), 3 name VARCHAR2(10), 4 sal NUMBER(6,2), 5 phone phone_type 6 ); 表已创建。 --4.PL/SQL记录表 --特性:处理多行多列数据;结合了PL/SQL记录与PL/SQL集合的优点; --demo1:PL/SQL块中使用PL/SQL记录表 SQL> SET SERVEROUTPUT ON; SQL> DECLARE 2 TYPE emp_table_type IS TABLE OF emp%ROWTYPE 3 INDEX BY BINARY_INTEGER; 4 emp_table emp_table_type; 5 BEGIN 6 SELECT * INTO emp_table(1) FROM emp 7 WHERE empno=&eno; 8 dbms_output.put_line('雇员名:'||emp_table(1).ename); 9 dbms_output.put_line('雇员工资:'||emp_table(1).sal); 10 END; 11 / 输入 eno 的值: 7788 原值 7: WHERE empno=&eno; 新值 7: WHERE empno=7788; 雇员名:SCOTT 雇员工资:1200 PL/SQL 过程已成功完成。 --5.多级集合 --demo1:在PL/SQL块中使用多级VARRAY SQL> DECLARE 2 --定义一维VARRAY 3 TYPE al_varray_type IS VARRAY(10) OF INT; 4 --定义二维VARRAY 5 TYPE nal_varray_type IS VARRAY(10) OF al_varray_type; 6 --初始化二维集合变量 7 nvl nal_varray_type:=nal_varray_type( 8 al_varray_type(1,2,3), 9 al_varray_type(4,5,6), 10 al_varray_type(7,8,9) 11 ); 12 BEGIN 13 dbms_output.put_line('显示二维数组所有元素'); 14 FOR i IN 1..nvl.COUNT LOOP 15 FOR j IN 1..nvl(i).COUNT LOOP 16 dbms_output.put_line('nvl('||i||','||j||')=' 17 ||nvl(i)(j)); 18 END LOOP; 19 END LOOP; 20 END; 21 / 显示二维数组所有元素 nvl(1,1)=1 nvl(1,2)=2 nvl(1,3)=3 nvl(2,1)=4 nvl(2,2)=5 nvl(2,3)=6 nvl(3,1)=7 nvl(3,2)=8 nvl(3,3)=9 PL/SQL 过程已成功完成。 --demo2:PL/SQL块中使用多级嵌套表 SQL> DECLARE 2 --定义一维嵌套表 3 TYPE al_table_type IS TABLE OF INT; 4 --定义二维嵌套表 5 TYPE nal_table_type IS TABLE OF al_table_type; 6 --初始化二维集合变量 7 nvl nal_table_type:=nal_table_type( 8 al_table_type(1,2,3), 9 al_table_type(4,5,6), 10 al_table_type(7,8,9) 11 ); 12 BEGIN 13 dbms_output.put_line('显示二维数组所有元素'); 14 FOR i IN 1..nvl.COUNT LOOP 15 FOR j IN 1..nvl(i).COUNT LOOP 16 dbms_output.put_line('nvl('||i||','||j||')=' 17 ||nvl(i)(j)); 18 END LOOP; 19 END LOOP; 20 END; 21 / 显示二维数组所有元素 nvl(1,1)=1 nvl(1,2)=2 nvl(1,3)=3 nvl(2,1)=4 nvl(2,2)=5 nvl(2,3)=6 nvl(3,1)=7 nvl(3,2)=8 nvl(3,3)=9 PL/SQL 过程已成功完成。 --demo3:PL/SQL中使用多级索引表 SQL> DECLARE 2 --定义一维索引表 3 TYPE al_table_type IS TABLE OF INT 4 INDEX BY BINARY_INTEGER; 5 --定义二维索引表 6 TYPE nal_table_type IS TABLE OF al_table_type 7 INDEX BY BINARY_INTEGER; 8 nvl nal_table_type; 9 BEGIN 10 nvl(1)(1):=1; 11 nvl(1)(2):=2; 12 nvl(1)(3):=3; 13 nvl(2)(1):=4; 14 nvl(2)(2):=5; 15 nvl(2)(3):=6; 16 nvl(3)(1):=7; 17 nvl(3)(2):=8; 18 nvl(3)(3):=9; 19 dbms_output.put_line('显示二维数组所有元素'); 20 FOR i IN 1..nvl.COUNT LOOP 21 FOR j IN 1..nvl(i).COUNT LOOP 22 dbms_output.put_line('nvl('||i||','||j||')=' 23 ||nvl(i)(j)); 24 END LOOP; 25 END LOOP; 26 END; 27 / 显示二维数组所有元素 nvl(1,1)=1 nvl(1,2)=2 nvl(1,3)=3 nvl(2,1)=4 nvl(2,2)=5 nvl(2,3)=6 nvl(3,1)=7 nvl(3,2)=8 nvl(3,3)=9 PL/SQL 过程已成功完成。 --(三).集合方法 --集合方法是Oracle提供的用于操作集合变量的内置函数或过程 --函数:EXISTS,COUNT,LIMIT,FIRST,NEXT,PRIOR,NEXT --过程:EXTEND,TRIM,DELETE --特性:集合方法只使用于PL/SQL,不适用于SQL语句中调用;EXTEND,TRIM只适用于嵌套表和VARRAY; --集合方法调用语法 collection_name.method_name[(parameters)] --1.EXISTS:确定集合元素是否存在,TRUE/FALSE SQL> DECLARE 2 TYPE ename_table_type IS TABLE OF emp.ename%TYPE; 3 ename_table ename_table_type; 4 BEGIN 5 IF ename_table.EXISTS(1) THEN 6 ename_table(1):='SCOTT'; 7 ELSE 8 dbms_output.put_line('嵌套表变量在PL/SQL块中使用时必须初始化'); 9 END IF; 10 END; 11 / 嵌套表变量在PL/SQL块中使用时必须初始化 PL/SQL 过程已成功完成。 --2.COUNT:集合元素个数 SQL> DECLARE 2 TYPE ename_table_type IS TABLE OF emp.ename%TYPE 3 INDEX BY BINARY_INTEGER; 4 ename_table ename_table_type; 5 TYPE sal_table_type IS TABLE OF emp.sal%TYPE 6 INDEX BY BINARY_INTEGER; 7 sal_table ename_table_type; 8 BEGIN 9 ename_table(-9):='SCOTT'; 10 ename_table(0):='SMITH'; 11 ename_table(9):='MARY'; 12 dbms_output.put_line('集合元素总个数:'||ename_table.COUNT); 13 dbms_output.put_line('集合元素总个数:'||sal_table.COUNT); 14 END; 15 / 集合元素总个数:3 集合元素总个数:0 PL/SQL 过程已成功完成。 --3.LIMIT:返回集合元素的最大个数,嵌套表和索引表的元素没有个数限制,返回NULL SQL> SET SERVEROUTPUT ON; SQL> DECLARE 2 TYPE ename_varray_type IS VARRAY(20) OF emp.ename%TYPE; 3 ename_varray ename_varray_type:=ename_varray_type('mary'); 4 TYPE ename_table_type IS TABLE OF emp.ename%TYPE; 5 ename_table ename_table_type:=ename_table_type('mary'); 6 BEGIN 7 dbms_output.put_line('ename_varray集合元素的最大个数:'||ename_varray.LIMIT); 8 dbms_output.put_line('ename_table集合元素的最大个数:'||ename_table.LIMIT); 9 END; 10 / ename_varray集合元素的最大个数:20 ename_table集合元素的最大个数: PL/SQL 过程已成功完成。 --4.FIRST和LAST返回集合变量第一个和最后一个的下标 SQL> SET SERVEROUTPUT ON; SQL> DECLARE 2 TYPE ename_varray_type IS VARRAY(20) OF emp.ename%TYPE; 3 ename_varray ename_varray_type:=ename_varray_type('mary','mary','mary','mary'); 4 TYPE ename_table_type IS TABLE OF emp.ename%TYPE; 5 ename_table ename_table_type:=ename_table_type('mary','mary','mary','mary'); 6 TYPE ename_table1_type IS TABLE OF emp.ename%TYPE 7 INDEX BY BINARY_INTEGER; 8 ename_table1 ename_table1_type; 9 BEGIN 10 ename_table(1):='SCOTT'; 11 ename_table(2):='TIGER'; 12 ename_table(3):='MARY'; 13 ename_table(4):='BLAKE'; 14 dbms_output.put_line('第一个元素:'||ename_table.FIRST); 15 dbms_output.put_line('最后一个元素:'||ename_table.LAST); 16 ename_varray(1):='SCOTT'; 17 ename_varray(2):='SMITH'; 18 ename_varray(3):='MARY'; 19 ename_varray(4):='BLAKE'; 20 dbms_output.put_line('第一个元素:'||ename_varray.FIRST); 21 dbms_output.put_line('最后一个元素:'||ename_varray.LAST); 22 ename_table1(-5):='SCOTT'; 23 ename_table1(1):='SMITH'; 24 ename_table1(5):='MARY'; 25 ename_table1(10):='BLAKE'; 26 dbms_output.put_line('第一个元素:'||ename_table1.FIRST); 27 dbms_output.put_line('最后一个元素:'||ename_table1.LAST); 28 END; 29 / 第一个元素:1 最后一个元素:4 第一个元素:1 最后一个元素:4 第一个元素:-5 最后一个元素:10 PL/SQL 过程已成功完成。 --5,PRIOR和NEXT:返回集合元素的前(后)一个元素的下标 SQL> SET SERVEROUTPUT ON; SQL> DECLARE 2 TYPE ename_table1_type IS TABLE OF emp.ename%TYPE 3 INDEX BY BINARY_INTEGER; 4 ename_table1 ename_table1_type; 5 BEGIN 6 ename_table1(-5):='SCOTT'; 7 ename_table1(1):='SMITH'; 8 ename_table1(5):='MARY'; 9 ename_table1(10):='BLAKE'; 10 dbms_output.put_line('元素5的前一个元素下标:'||ename_table1.PRIOR(5)); 11 dbms_output.put_line('元素5的后一个元素下标:'||ename_table1.NEXT(5)); 12 dbms_output.put_line('元素-5的后一个元素下标:'||ename_table1.PRIOR(-5)); 13 dbms_output.put_line('元素10的后一个元素下标:'||ename_table1.NEXT(10)); 14 END; 15 / 元素5的前一个元素下标:1 元素5的后一个元素下标:10 元素-5的后一个元素下标: 元素10的后一个元素下标: PL/SQL 过程已成功完成。 --6,EXTEND:改变原有集合的尺寸,只适用于嵌套表和VARRAY --EXTEND:为集合添加一个NULL元素;EXTEND(n):为集合添加n个NULL元素;EXTEND(n,i):为集合添加n个与第i个元素的值相同的元素; SQL> DECLARE 2 TYPE ename_table_type IS TABLE OF emp.ename%TYPE; 3 ename_table ename_table_type; 4 TYPE ename_table_type1 IS TABLE OF emp.ename%TYPE; 5 ename_table1 ename_table_type1; 6 TYPE ename_table_type2 IS TABLE OF emp.ename%TYPE; 7 ename_table2 ename_table_type2; 8 BEGIN 9 ename_table:=ename_table_type('MARY'); 10 ename_table1:=ename_table_type1('MARY'); 11 ename_table2:=ename_table_type2('MARY'); 12 ename_table.EXTEND(5,1); 13 ename_table1.EXTEND(5); 14 ename_table2.EXTEND(); 15 dbms_output.put_line('ename_table的元素个数为:'||ename_table.COUNT); 16 dbms_output.put_line('ename_table1的元素个数为:'||ename_table1.COUNT); 17 dbms_output.put_line('ename_table2的元素个数为:'||ename_table2.COUNT); 18 END; 19 / ename_table的元素个数为:6 ename_table1的元素个数为:6 ename_table2的元素个数为:2 PL/SQL 过程已成功完成。 --7:TRIM与DELETE --TRIM:删除尾部元素,适用于嵌套表和和VARRAY --DELETE:删除集合中的元素,适用于嵌套表和索引表 --TRIM:删除尾部元素; --TRIM(n):删除尾部n个元素; --DELETE:删除集合中所有元素; --DELETE(n):删除集合中第n个元素; --DELETE(m,n):删除集合中第m到n个元素; SQL> DECLARE 2 TYPE ename_table_type IS TABLE OF emp.ename%TYPE; 3 ename_table ename_table_type; 4 TYPE ename_table_type1 IS TABLE OF emp.ename%TYPE 5 INDEX BY BINARY_INTEGER; 6 ename_table1 ename_table_type1; 7 TYPE ename_varray_type IS VARRAY(20) OF emp.ename%TYPE; 8 ename_varray ename_varray_type; 9 BEGIN 10 ename_table:=ename_table_type('SCOTT','TIGER','NIOR','SMITH','MARY'); 11 ename_table1(-5):='SS'; 12 ename_table1(0):='TT'; 13 ename_table1(4):='WW'; 14 ename_table1(10):='GG'; 15 ename_varray:=ename_varray_type('张三','李四','王五','赵六'); 16 17 dbms_output.put_line('-------ename_table:'||ename_table.COUNT); 18 ename_table.TRIM(); 19 dbms_output.put_line('ename_table-TRIM:'||ename_table.COUNT); 20 ename_table.TRIM(2); 21 dbms_output.put_line('ename_table-TRIM(2):'||ename_table.COUNT); 22 23 dbms_output.put_line('-----ename_table1:'||ename_table1.COUNT); 24 ename_table1.DELETE(4); 25 dbms_output.put_line('ename_table1-DELETE(4):'||ename_table1.COUNT); 26 ename_table1.DELETE(0,10); 27 dbms_output.put_line('ename_table1-DELETE(0,10):'||ename_table1.COUNT); 28 29 dbms_output.put_line('-----ename_varray:'||ename_varray.COUNT); 30 ename_varray.TRIM(); 31 dbms_output.put_line('ename_varray-TRIM:'||ename_varray.COUNT); 32 ename_varray.TRIM(2); 33 dbms_output.put_line('ename_varray-TRIM(2):'||ename_varray.COUNT); 34 END; 35 / -------ename_table:5 ename_table-TRIM:4 ename_table-TRIM(2):2 -----ename_table1:4 ename_table1-DELETE(4):3 ename_table1-DELETE(0,10):1 -----ename_varray:4 ename_varray-TRIM:3 ename_varray-TRIM(2):1 PL/SQL 过程已成功完成。 --(四),集合赋值 --嵌套表和VARRAY --1.将一个集合赋值给另一个集合 --要求集合的类型必须相同 SQL> SET SERVEROUTPUT ON; SQL> DECLARE 2 TYPE name_varray_type IS VARRAY(4) OF VARCHAR2(40); 3 name_varray1 name_varray_type:=name_varray_type('SCOTT','SMITH'); 4 name_varray2 name_varray_type; 5 BEGIN 6 FOR i IN 1..name_varray1.COUNT LOOP 7 dbms_output.put_line('name_varray1_ini:'||name_varray1(i)); 8 END LOOP; 9 name_varray2:=name_varray1; 10 FOR i IN 1..name_varray2.COUNT LOOP 11 dbms_output.put_line('name_varray2_ini:'||name_varray2(i)); 12 END LOOP; 13 END; 14 / name_varray1_ini:SCOTT name_varray1_ini:SMITH name_varray2_ini:SCOTT name_varray2_ini:SMITH PL/SQL 过程已成功完成。 --2.给集合赋NULL SQL> SET SERVEROUTPUT ON; SQL> DECLARE 2 TYPE name_varray_type IS VARRAY(4) OF VARCHAR2(40); 3 name_varray1 name_varray_type:=name_varray_type('SCOTT','SMITH'); 4 name_varray2 name_varray_type; 5 BEGIN 6 FOR i IN 1..name_varray1.COUNT LOOP 7 dbms_output.put_line('name_varray1_ini:'||name_varray1(i)); 8 END LOOP; 9 name_varray1:=name_varray2; 10 IF name_varray1 IS NULL THEN 11 dbms_output.put_line('name_varray1的现有元素个数为:0'); 12 END IF; 13 END; 14 / name_varray1_ini:SCOTT name_varray1_ini:SMITH name_varray1的现有元素个数为:0 PL/SQL 过程已成功完成。 --3.集合操作符给嵌套表赋值 --SET,MULTISET UNION,MULTISET UNION DISTINCT,MULTISET INTERSECT,MULTISET EXCEPT; --SET去重 SQL> DECLARE 2 TYPE temp_table_type IS TABLE OF NUMBER; 3 temp_table temp_table_type:=temp_table_type(1,2,2,3,4,5,6,6); 4 BEGIN 5 temp_table:=SET(temp_table); 6 FOR i IN 1..temp_table.COUNT LOOP 7 dbms_output.put_line('temp_table_values:'||temp_table(i)); 8 END LOOP; 9 END; 10 / temp_table_values:1 temp_table_values:2 temp_table_values:3 temp_table_values:4 temp_table_values:5 temp_table_values:6 PL/SQL 过程已成功完成。 --MULTISET UNION 取并集 SQL> DECLARE 2 TYPE temp_table_type IS TABLE OF NUMBER; 3 temp1_table temp_table_type:=temp_table_type(5,6,7,8); 4 temp2_table temp_table_type:=temp_table_type(1,2,3,4); 5 BEGIN 6 temp1_table:=temp1_table MULTISET UNION temp2_table; 7 FOR i IN 1..temp1_table.COUNT LOOP 8 dbms_output.put_line('temp1_table_values:'||temp1_table(i)); 9 END LOOP; 10 END; 11 / temp1_table_values:5 temp1_table_values:6 temp1_table_values:7 temp1_table_values:8 temp1_table_values:1 temp1_table_values:2 temp1_table_values:3 temp1_table_values:4 PL/SQL 过程已成功完成。 --MULTISET UNION DISTINCT取非交集部分数据 SQL> DECLARE 2 TYPE temp_table_type IS TABLE OF NUMBER; 3 temp1_table temp_table_type:=temp_table_type(5,5,7,8); 4 temp2_table temp_table_type:=temp_table_type(1,2,2,3); 5 BEGIN 6 temp1_table:=temp1_table MULTISET UNION DISTINCT temp2_table; 7 FOR i IN 1..temp1_table.COUNT LOOP 8 dbms_output.put_line('temp1_table_values:'||temp1_table(i)); 9 END LOOP; 10 END; 11 / temp1_table_values:5 temp1_table_values:7 temp1_table_values:8 temp1_table_values:1 temp1_table_values:2 temp1_table_values:3 PL/SQL 过程已成功完成。 --MULTISET INTERSECT SQL> DECLARE 2 TYPE temp_table_type IS TABLE OF NUMBER; 3 temp1_table temp_table_type:=temp_table_type(5,6,7,8); 4 temp2_table temp_table_type:=temp_table_type(2,3,4,5); 5 BEGIN 6 temp1_table:=temp1_table MULTISET INTERSECT temp2_table; 7 FOR i IN 1..temp1_table.COUNT LOOP 8 dbms_output.put_line('temp1_table_values:'||temp1_table(i)); 9 END LOOP; 10 END; 11 / temp1_table_values:5 PL/SQL 过程已成功完成。 --MULTISET EXCEPT取左边非交集部分 SQL> DECLARE 2 TYPE temp_table_type IS TABLE OF NUMBER; 3 temp1_table temp_table_type:=temp_table_type(5,6,7,8); 4 temp2_table temp_table_type:=temp_table_type(2,3,4,5); 5 BEGIN 6 temp1_table:=temp1_table MULTISET EXCEPT temp2_table; 7 FOR i IN 1..temp1_table.COUNT LOOP 8 dbms_output.put_line('temp1_table_values:'||temp1_table(i)); 9 END LOOP; 10 END; 11 / temp1_table_values:6 temp1_table_values:7 temp1_table_values:8 PL/SQL 过程已成功完成。 --(五),集合比较 --IS NULL,IS EMPTY,=,CARDINALITY(),MEMBER OF,IS A SET,SUBMULTISET OF; --CARDINALITY:返回元素个数 SQL> DECLARE 2 TYPE temp_table_type IS TABLE OF NUMBER; 3 temp1_table temp_table_type:=temp_table_type(5,6,7,8); 4 BEGIN 5 dbms_output.put_line('temp1_table_CountValues:'||CARDINALITY(temp1_table)); 6 END; 7 / temp1_table_CountValues:4 PL/SQL 过程已成功完成。 --MEMBER OF:判断元素是否在另一个元素中 SQL> DECLARE 2 TYPE temp_table_type IS TABLE OF NUMBER; 3 temp1_table temp_table_type:=temp_table_type(5,6,7,8); 4 temp2 NUMBER:=5; 5 BEGIN 6 IF temp2 MEMBER OF temp1_table THEN 7 dbms_output.put_line('temp2:'||temp2); 8 END IF; 9 END; 10 / temp2:5 PL/SQL 过程已成功完成。 --SUBMULTISET OF:判断一个嵌套表是否为另一个嵌套表的子集 SQL> DECLARE 2 TYPE temp_table_type IS TABLE OF NUMBER; 3 temp1_table temp_table_type:=temp_table_type(5,6,7,8); 4 temp2_table temp_table_type:=temp_table_type(5,6); 5 temp3_table temp_table_type:=temp_table_type(7,9); 6 BEGIN 7 IF temp2_table SUBMULTISET OF temp1_table THEN 8 FOR i IN 1..temp2_table.COUNT LOOP 9 dbms_output.put_line('temp2_table:'||temp2_table(i)); 10 END LOOP; 11 END IF; 12 IF temp3_table SUBMULTISET OF temp1_table THEN 13 FOR i IN 1..temp3_table.COUNT LOOP 14 dbms_output.put_line('temp3_table:'||temp3_table(i)); 15 END LOOP; 16 END IF; 17 END; 18 / temp2_table:5 temp2_table:6 PL/SQL 过程已成功完成。 --IS A SET:判断一个集合中是否有重复的值 SQL> DECLARE 2 TYPE temp_table_type IS TABLE OF NUMBER; 3 temp1_table temp_table_type:=temp_table_type(5,5,6,7,8); 4 temp2_table temp_table_type:=temp_table_type(5,6,7,8); 5 BEGIN 6 IF temp1_table IS A SET THEN 7 FOR i IN 1..temp1_table.COUNT LOOP 8 dbms_output.put_line('temp1_table:'||temp1_table(i)); 9 END LOOP; 10 END IF; 11 IF temp2_table IS A SET THEN 12 FOR i IN 1..temp2_table.COUNT LOOP 13 dbms_output.put_line('temp2_table:'||temp2_table(i)); 14 END LOOP; 15 END IF; 16 END; 17 / temp2_table:5 temp2_table:6 temp2_table:7 temp2_table:8 PL/SQL 过程已成功完成。 --(五),批量绑定 --1.使用批量绑定与不使用批量绑定耗时DEMO对比 SQL> CREATE TABLE demo 2 ( 3 id NUMBER(6) PRIMARY KEY, 4 name VARCHAR2(10) 5 ); 表已创建。 SQL> SET SERVEROUTPUT ON; SQL> DECLARE 2 TYPE id_table_type IS TABLE OF NUMBER(6) 3 INDEX BY BINARY_INTEGER; 4 TYPE name_table_type IS TABLE OF VARCHAR2(10) 5 INDEX BY BINARY_INTEGER; 6 id_table id_table_type; 7 name_table name_table_type; 8 start_time NUMBER(10); 9 end_time NUMBER(10); 10 BEGIN 11 FOR i IN 1..50000 LOOP 12 id_table(i):=i; 13 name_table(i):='Name_'||to_char(i); 14 END LOOP; 15 start_time:=dbms_utility.get_time; 16 FOR i IN 1..id_table.COUNT LOOP 17 INSERT INTO demo VALUES(id_table(i),name_table(i)); 18 END LOOP; 19 end_time:=dbms_utility.get_time; 20 dbms_output.put_line('总时间(秒):'||to_char((end_time-start_time)/100)); 21 END; 22 / 总时间(秒):3.72 PL/SQL 过程已成功完成。 SQL> DROP TABLE demo; 表已删除。 SQL> CREATE TABLE demo 2 ( 3 id NUMBER(6) PRIMARY KEY, 4 name VARCHAR2(10) 5 ); 表已创建。 SQL> SET SERVEROUTPUT ON; SQL> DECLARE 2 TYPE id_table_type IS TABLE OF NUMBER(6) 3 INDEX BY BINARY_INTEGER; 4 TYPE name_table_type IS TABLE OF VARCHAR2(10) 5 INDEX BY BINARY_INTEGER; 6 id_table id_table_type; 7 name_table name_table_type; 8 start_time NUMBER(10); 9 end_time NUMBER(10); 10 BEGIN 11 FOR i IN 1..50000 LOOP 12 id_table(i):=i; 13 name_table(i):='Name_'||to_char(i); 14 END LOOP; 15 start_time:=dbms_utility.get_time; 16 FORALL i IN 1..id_table.COUNT 17 INSERT INTO demo VALUES(id_table(i),name_table(i)); 18 end_time:=dbms_utility.get_time; 19 dbms_output.put_line('总时间(秒):'||to_char((end_time-start_time)/100)); 20 END; 21 / 总时间(秒):.33 PL/SQL 过程已成功完成。 --2.使用FORALL的几种用法 --语法1 FORALL index IN lower_bound..upper_bound sql_statement; --语法2 FORALL index IN INDICES OF collection [BETWEEN lower_bound.AND.upper_bound] sql_statement; --语法3 FORALL index IN VALUES OF index_collection sql_statement; --INSERT,UPDATE,DELETE中均可以使用批量绑定 --FORALL i IN 8..10 --FORALL i IN INDICES OF id_table:使用批量绑定跳过NULL集合元素 --FORALL i IN VALUES OF id_table:使用批量绑定访问指定值得集合元素 --sql%bulk_rowcount(2):返回第二个元素作用的行数 --3.BULK COLLECT --用于取得批量数据,只能在SLECT INTO,FETCH INTO,DML返回子句 --DEMO1 SQL> DECLARE 2 TYPE id_table_type IS TABLE OF NUMBER(6) 3 INDEX BY BINARY_INTEGER; 4 TYPE name_table_type IS TABLE OF VARCHAR2(10) 5 INDEX BY BINARY_INTEGER; 6 id_table id_table_type; 7 name_table name_table_type; 8 BEGIN 9 SELECT * BULK COLLECT INTO id_table,name_table FROM demo; 10 FOR i IN 1..id_table.COUNT LOOP 11 IF i<10 THEN 12 dbms_output.put_line('id_table:'||id_table(i)); 13 dbms_output.put_line('name_table:'||name_table(i)); 14 END IF; 15 END LOOP; 16 END; 17 / id_table:819 name_table:Name_819 id_table:820 name_table:Name_820 id_table:821 name_table:Name_821 id_table:822 name_table:Name_822 id_table:823 name_table:Name_823 id_table:824 name_table:Name_824 id_table:825 name_table:Name_825 id_table:826 name_table:Name_826 id_table:827 name_table:Name_827 PL/SQL 过程已成功完成。 --DEMO2 SQL> DECLARE 2 TYPE ename_table_type IS TABLE OF emp.ename%TYPE; 3 ename_table ename_table_type; 4 BEGIN 5 DELETE FROM emp WHERE deptno=&no 6 RETURNING ename BULK COLLECT INTO ename_table; 7 dbms_output.put('雇员名:'); 8 FOR i IN 1..ename_table.COUNT LOOP 9 dbms_output.put(ename_table(i)||' '); 10 END LOOP; 11 dbms_output.new_line; 12 END; 13 / 输入 no 的值: 10 原值 5: DELETE FROM emp WHERE deptno=&no 新值 5: DELETE FROM emp WHERE deptno=10 雇员名:CLARK KING MILLER PL/SQL 过程已成功完成。