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 过程已成功完成。

 

你可能感兴趣的:(pl/sql)