oracle 记录和数组,数组、记录、嵌套表的使用

Oracle学习:PL/SQL中的集合类型分析

三种集合分类的区别之一是, Nested

table与VARRY既可以被用于PL/SQL,也可以被直接用于数据库中,但是Associative

array不行,也就是说,Associative array是不能通过CREATE

TYPE语句进行单独创建,只能在PL/SQL块(或Package)中进行定义并使用(即适用范围是PL/SQL

Block级别),而Nested table与VARRAY则可以使用CREATE

TYPE进行创建(即适用范围是Schema级别),它们还可以直接作为数据库表中列的类型。

Associative array

CREATE OR REPLACE TYPE ib_planguage IS TABLE OF VARCHAR2(10)

INDEX BY PLS_INTEGER;

通不过

PLS-00355: use of pl/sql table not allowed in this context

在块中

TYPE ib_planguage IS TABLE OF VARCHAR2(10)INDEX BY

PLS_INTEGER;

--下标是BY PLS_INTEGER,数据是varchar2(10)。

可以用。

Nested table (嵌套表)

CREATE OR REPLACE TYPE nt_planguage IS TABLE

OF VARCHAR2(10);

定义可以在使用。

a4c26d1e5885305701be709a3d33442f.png

------------

TYPE varTabType IS TABLE

OF varchar2(10) INDEX BY

PLS_INTEGER;

--下标是BY PLS_INTEGER,数据是varchar2(10)。

TYPE population_type IS TABLE OF

NUMBER INDEX BY

VARCHAR2(64);--下标是字符串,数据是number。

country_population

population_type;声明后可以直接用,

continent_population('Australia') :=

30000000;

continent_population('Antarctica') := 1000;

-- 新下标

continent_population('Antarctica') := 1001;

-- 更新以前的

DECLARE

TYPE nested_type IS TABLE OF

VARCHAR2(30); --

一维,数据为VARCHAR2(30); TYPE varray_type IS VARRAY(5)

OF INTEGER;

TYPE assoc_array_num_type IS

TABLE OF NUMBER INDEX BY PLS_INTEGER;

TYPE assoc_array_str_type IS

TABLE OF VARCHAR2(32) INDEX BY PLS_INTEGER;

TYPE assoc_array_str_type2 IS

TABLE OF VARCHAR2(32) INDEX BY VARCHAR2(64);

v1 nested_type;

v2 varray_type;

v3 assoc_array_num_type;

v4 assoc_array_str_type;

v5

assoc_array_str_type2;

BEGIN

-- an arbitrary number of strings can be inserted v1

v1 :=

nested_type('Shipping','Sales','Finance','Payroll');

v2 := varray_type(1, 2, 3, 4,

5); -- Up to 5 integers

v3(99) := 10; -- Just start

assigning to elements

v3(7) := 100; -- Subscripts

can be any integer values

v4(42) := 'Smith'; -- Just

start assigning to elements

v4(54) := 'Jones'; --

Subscripts can be any integer values

v5('Canada') := 'North

America'; -- Just start assigning to elements

v5('Greece') :=

'Europe'; -- Subscripts can be string values

END;

--可以这样在包头里定义类型,然后使用。

CREATE PACKAGE personnel AS

TYPE staff_list IS TABLE OF

employees.employee_id%TYPE;

PROCEDURE award_bonuses

(empleos_buenos IN staff_list);

END personnel;

/

CREATE PACKAGE BODY personnel AS

PROCEDURE award_bonuses (empleos_buenos staff_list) IS

BEGIN

FOR i IN

empleos_buenos.FIRST..empleos_buenos.LAST

LOOP

UPDATE employees SET salary = salary + 100

WHERE employees.employee_id = empleos_buenos(i);

END LOOP;

END;

END;

/

DECLARE

good_employees personnel.staff_list;

BEGIN

good_employees := personnel.staff_list(100, 103, 107);

personnel.award_bonuses (good_employees);

END;

/

--类似二维数组的定义。

DECLARE

TYPE name_rec IS

RECORD ( first_name VARCHAR2(20), last_name

VARCHAR2(25) );

TYPE names IS VARRAY(250) OF

name_rec; --以name_rec为数据的数组,有250个下标。

BEGIN

NULL; --怎么使用呢??

END;

/

DECLARE

TYPE dnames_tab IS TABLE OF

VARCHAR2(30); --

一维下标为数字,内容为varchar2(30)

dept_names dnames_tab;

BEGIN

dept_names :=

dnames_tab('Shipping','Sales','Finance','Payroll'); --需要初始化

END;

/

DECLARE

-- In the varray, we put an upper limit on the number of

elements

TYPE dnames_var IS VARRAY(20)

OF VARCHAR2(30); -- 一维下标为数字,内容为字符串

dept_names dnames_var;

BEGIN

-- Because dnames is declared as VARRAY(20), we can put up to 10--

elements in the constructor

-- 因为dnames被宣布为VARRAY(20),我们可以将10——元素在构造函数中

dept_names :=

dnames_var('Shipping','Sales','Finance','Payroll');

END;

/

DECLARE

TYPE dnames_tab IS TABLE OF

VARCHAR2(30);

dept_names dnames_tab;

TYPE dnamesNoNulls_type IS

TABLE OF VARCHAR2(30) NOT NULL;

BEGIN

dept_names :=

dnames_tab('Shipping', NULL,'Finance',

NULL);

-- If dept_names was of type dnamesNoNulls_type, we could not

include null values in the constructor

-- 如果部门dnamesNoNulls_type类型的名字,我们不能包含null值在构造函数中

END;

/

DECLARE

TYPE dnames_tab IS TABLE OF

VARCHAR2(30);

dept_names dnames_tab :=

dnames_tab('Shipping','Sales','Finance','Payroll');

BEGIN

NULL;

END;

/

DECLARE

TYPE dnames_var IS VARRAY(20)

OF VARCHAR2(30); --20个元素,每个为VARCHAR2(30)

dept_names

dnames_var;

BEGIN

IF dept_names IS NULL

THEN

DBMS_OUTPUT.PUT_LINE('初始化以前,数组是空的.');

-- While the varray is null, we cannot check its COUNT

attribute.

-- DBMS_OUTPUT.PUT_LINE('有 ' ||

dept_names.COUNT || ' 元素.');

ELSE

DBMS_OUTPUT.PUT_LINE('初始化前,数组不是空的。');

END IF;

dept_names := dnames_var(); --

initialize empty varray

IF dept_names IS NULL

THEN

DBMS_OUTPUT.PUT_LINE('初始化以后,数组是空的.');

ELSE

DBMS_OUTPUT.PUT_LINE('初始化后,数组不是空的。');

DBMS_OUTPUT.PUT_LINE('有 ' || dept_names.COUNT || ' 元素.');

END IF;

dept_names := dnames_var('12','323'); --

IF dept_names IS NULL THEN

DBMS_OUTPUT.PUT_LINE('初始化后,加2个元素,数组是空的.');

ELSE

DBMS_OUTPUT.PUT_LINE('初始化后,加2个元素');

DBMS_OUTPUT.PUT_LINE('有 ' || dept_names.COUNT || ' 元素.');

END IF;

END;

/

运行结果

初始化以前,数组是空的.

初始化后,数组不是空的。

有 0 元素.

初始化后,加2个元素

有 2 元素.

DECLARE

TYPE sum_multiples IS TABLE OF PLS_INTEGER INDEX

BY PLS_INTEGER;

n PLS_INTEGER :=

5; -- number of multiples to

sum for display

sn PLS_INTEGER := 10; --

number of multiples to sum

m PLS_INTEGER :=

6; -- multiple

FUNCTION get_sum_multiples(multiple IN PLS_INTEGER, num IN

PLS_INTEGER)

RETURN sum_multiples IS

s sum_multiples;

BEGIN

FOR i IN 1..num LOOP

s(i) := multiple * ((i * (i + 1)) / 2) ; -- sum of multiples

END LOOP;

RETURN

s;

END get_sum_multiples;

BEGIN

-- call function to retrieve the element identified by subscript

(key)

for i in 1..n loop

DBMS_OUTPUT.PUT_LINE('Sum of the first ' ||

TO_CHAR(i) || ' multiples of ' ||

TO_CHAR(m) || ' is ' || TO_CHAR(get_sum_multiples (m,

sn)(i)));

end loop;

END;

/

结果

SQL>

Sum of the first 1 multiples of 3 is 3

Sum of the first 2 multiples of 3 is

9 3+3*2

Sum of the first 3 multiples of 3 is

18 9+3*3

Sum of the first 4 multiples of 3 is

30 18+3*4

Sum of the first 5 multiples of 3 is

45 30+3*5

PL/SQL procedure successfully completed

SQL>

Sum of the first 1 multiples of 6 is 6

Sum of the first 2 multiples of 6 is

18 6+6*2

Sum of the first 3 multiples of 6 is

36 18+6*3

Sum of the first 4 multiples of 6 is

60 36+6*4

Sum of the first 5 multiples of 6 is

90 60+6*5

DECLARE

TYPE last_name_typ IS

VARRAY(3) OF VARCHAR2(64);

TYPE surname_typ IS VARRAY(3)

OF VARCHAR2(64);

-- 定义的一样,但是被看做是两种类型,之后不能相互赋值。

group1 last_name_typ :=

last_name_typ('Jones','Wong','Marceau');

group2 last_name_typ :=

last_name_typ('Klein','Patsos','Singh');

-- This third variable has a similar declaration, but is not the

same type.

group3 surname_typ :=

surname_typ('Trevisi','Macleod','Marquez');

BEGIN

-- Allowed because they have the same datatype

group1 := group2;

-- Not allowed because they have different datatypes

-- group3

:= group2; -- raises an error

-- PLS-00382: expression is of wrong type

END;

/

DECLARE

TYPE nested_typ IS TABLE OF NUMBER;

nt1 nested_typ := nested_typ(1,11,12);

nt2 nested_typ := nested_typ(23,32,33,3);

nt3 nested_typ :=

nested_typ(23,33,33,21); nt4 nested_typ := nested_typ(41,41,22);

answer nested_typ;

-- The results might be in a different order than you expect.

-- Remember, you should not rely on the order of elements in nested

tables.

PROCEDURE print_nested_table(the_nt nested_typ)

IS

output VARCHAR2(128);

BEGIN

IF the_nt IS NULL THEN

DBMS_OUTPUT.PUT_LINE('Results:

');

RETURN;

END IF;

IF the_nt.COUNT = 0 THEN

DBMS_OUTPUT.PUT_LINE('Results: empty set');

RETURN;

END IF;

FOR i IN the_nt.FIRST .. the_nt.LAST

LOOP

output := output || the_nt(i) || ' ';

END LOOP;

DBMS_OUTPUT.PUT_LINE('Results: ' || output);

END;

BEGIN

answer := nt1 MULTISET UNION nt4; -- 并集

print_nested_table(answer);

answer := nt1 MULTISET UNION nt3; -- 并集

print_nested_table(answer);

answer := nt1 MULTISET UNION DISTINCT nt3; --

并集后取唯一

print_nested_table(answer);

answer := nt2 MULTISET INTERSECT nt3; --

交集

print_nested_table(answer);

answer := nt2 MULTISET INTERSECT DISTINCT nt3;

-- 交集后取唯一

print_nested_table(answer);

answer := SET(nt3); -- 去重复

print_nested_table(answer);

answer := nt3 MULTISET EXCEPT nt2; --

减 print_nested_table(answer);

answer := nt3 MULTISET EXCEPT DISTINCT nt2; --

减后取唯一

print_nested_table(answer);

END;

/

Results: 1 11 12 41 41 22

Results: 1 11 12 23 33 33 21

Results: 1 11 12 23 33 21

Results: 23 33

Results: 23 33

Results: 23 33 21

Results: 33 21

Results: 21

DECLARE

TYPE obj_name_rec is

RECORD (

object_name user_objects.OBJECT_NAME%TYPE,

object_id user_objects.OBJECT_ID%TYPE,

object_type user_objects.OBJECT_TYPE%TYPE

);

-- Array type that can hold information 10 employees

TYPE

objList_arr IS VARRAY(10) OF obj_name_rec;

objs

objList_arr; -- Declare a cursor to select a subset of columns.

CURSOR

c1 IS SELECT object_name,object_id,object_type FROM

user_objects;

Type NameSet IS TABLE OF

c1%ROWTYPE;

SeniorTen NameSet;

EndCounter NUMBER :=

10;

BEGIN

objs := objList_arr();

SELECT object_name,object_id,object_type

BULK COLLECT INTO SeniorTen FROM

user_objects WHERE object_type = 'TABLE' ORDER BY object_id;

IF SeniorTen.LAST > 0

THEN

IF

SeniorTen.LAST < 10 THEN EndCounter :=

SeniorTen.LAST;

END

IF;

FOR i in

1..EndCounter LOOP

objs.EXTEND(1); objs(i) := SeniorTen(i);

DBMS_OUTPUT.PUT_LINE(objs(i).object_name || ', '

|| objs(i).object_id || ', ' ||

objs(i).object_type);

END

LOOP;

END IF;

END;

/

DECLARE

TYPE emp_name_rec is RECORD (

firstname employees.first_name%TYPE,

lastname employees.last_name%TYPE,

hiredate employees.hire_date%TYPE

);

-- Table type that can hold information about employees

TYPE EmpList_tab IS TABLE OF emp_name_rec;

SeniorSalespeople EmpList_tab;

-- Declare a cursor to select a subset of columns.

CURSOR c1 IS SELECT first_name, last_name, hire_date FROM employees;

EndCounter NUMBER := 10;

TYPE EmpCurTyp IS REF CURSOR;

emp_cv EmpCurTyp;

BEGIN

OPEN emp_cv FOR SELECT first_name, last_name, hire_date FROM employees

WHERE job_id = 'SA_REP' ORDER BY hire_date;

FETCH emp_cv BULK COLLECT INTO SeniorSalespeople;

CLOSE emp_cv;

-- for this example, display a maximum of ten employees

IF SeniorSalespeople.LAST > 0 THEN

IF SeniorSalespeople.LAST < 10 THEN EndCounter := SeniorSalespeople.LAST;

END IF;

FOR i in 1..EndCounter LOOP

DBMS_OUTPUT.PUT_LINE(SeniorSalespeople(i).lastname || ', '

|| SeniorSalespeople(i).firstname || ', ' || SeniorSalespeople(i).hiredate);

END LOOP;

END IF;

END;

/

DECLARE

TYPE nested_typ IS TABLE

OF NUMBER;

nt1 nested_typ := nested_typ(1,2,3);

nt2 nested_typ := nested_typ(3,2,1);

nt3 nested_typ := nested_typ(2,3,1,3);

nt4 nested_typ := nested_typ(1,2,5);

answer BOOLEAN;

howmany NUMBER;

PROCEDURE testify(truth BOOLEAN DEFAULT NULL,

quantity NUMBER DEFAULT NULL) IS

BEGIN

IF truth IS

NOT NULL THEN

DBMS_OUTPUT.PUT_LINE(CASE truth WHEN TRUE THEN 'True' WHEN FALSE

THEN 'False' END);

END

IF;

IF quantity

IS NOT NULL THEN

DBMS_OUTPUT.PUT_LINE(quantity);

END

IF;

END;

BEGIN

answer := nt1 IN (nt2,nt3,nt4); -- true, nt1 在

nt2,nt3,nt4的并集中,似乎不完全是。

testify(truth => answer);

answer := nt1 SUBMULTISET OF nt4; --

true, nt1 是 nt4 的子集

testify(truth => answer);

answer := nt1 NOT SUBMULTISET OF nt4; --

testify(truth => answer);

howmany := CARDINALITY(nt3); -- nt3的元素个数

testify(quantity =>

howmany);

howmany := CARDINALITY(SET(nt3)); --

nt3的基本的元素个数

testify(quantity =>

howmany);

answer := 2 MEMBER OF nt1; --

判数据是否属于nt1中的元素

testify(truth => answer);

answer := nt3 IS A SET; -- false, nt3 has

duplicates

testify(truth => answer);

answer := nt3 IS NOT A SET; -- true, nt3 has

duplicates

testify(truth => answer);

answer := nt1 IS EMPTY; -- nt1 为空

testify(truth => answer);

END;

/

DECLARE

TYPE t1 IS VARRAY(10) OF

INTEGER; -- 以整数

为数据的10个元素的数组 TYPE nt1 IS VARRAY(10) OF t1; -- multilevel varray

type 以t1为数据的10个元素的数组 va t1 :=

t1(2,3,5);

-- initialize multilevel varray

nva nt1 := nt1(va, t1(55,6,73),

t1(2,4), va);

i INTEGER;

va1 t1;

BEGIN

-- multilevel access

i := nva(2)(3); -- i will get value 73

DBMS_OUTPUT.PUT_LINE('I = ' || i);

-- add a new varray element to nva

nva.EXTEND; --扩展

-- replace inner varray elements

nva(5) := t1(56,

32); nva(4) := t1(45,43,67,43345); --可以写10个

-- replace an inner integer element

nva(4)(4) := 1; -- replaces 43345 with 1

-- add a new element to the 4th varray element

-- and store integer 89 into it.

nva(4).EXTEND;

nva(4)(5) := 89;

END;

/

DECLARE

TYPE tb1 IS TABLE OF

VARCHAR2(20); --以varchar2(20)为元素的嵌套表

TYPE Ntb1 IS TABLE OF tb1; -- table of table

elements --以 tb1 为元素的嵌套表

TYPE Tv1 IS VARRAY(10) OF

INTEGER; --以整数 为元素的一维数组

TYPE ntb2 IS TABLE OF tv1; -- table of varray

elements 以tv1

为元素的一维数组

vtb1 tb1 := tb1('one', 'three');

vntb1 ntb1 := ntb1(vtb1);

vntb2 ntb2 := ntb2(tv1(3,5), tv1(5,7,3)); --

table of varray elements

BEGIN

vntb1.EXTEND; vntb1(2) :=

vntb1(1);

-- delete the first element in vntb1

vntb1.DELETE(1);

-- delete the first string from the second table in the nested

table

vntb1(2).DELETE(1);

END;

/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值