Conllection Type
PL/SQL has Collection Type: associative array] [1], VARRAY [(variable-size array)] [1], and nested table. All three declarations must be initialized, VARRAY and Nestes Table have constructors, and associative arraty [1] has no constructors.
[[VARRAY] [1]: You can modify and initialize arrays with constructors or access them with subscripts:
set serveroutput on;
DECLARE
TYPE People IS VARRAY(10) OF VARCHAR2(12);
Stu People := People('Yang','Wang','Zhang','Li');
PROCEDURE print_item(
parm_head VARCHAR2)
IS
BEGIN
dbms_output.put_line(parm_head);
FOR i IN Stu.FIRST .. Stu.LAST
LOOP
dbms_output.put_line(i ||' : '|| Stu(i));
END LOOP;
dbms_output.put_line('________________');
END;
BEGIN
print_item('First:"');
Stu(2) := 'kai';
print_item('Seccend:');
Stu := People('Wu','Gu','Text','helo');
print_item('Three:');
end;
In the example above, it is also true to replace VARRAY with TABLE (nested table) when defining a type.
While can also be used in loops, but a little change is needed if access is done through the methods he provides internally:
SET serveroutput ON;
DECLARE
TYPE People IS VARRAY(10) OF VARCHAR2(12);
Stu People := People('Yang','Wang','Zhang','Li');
i PLS_INTEGER := Stu.FIRST;
PROCEDURE print_item(
parm_head VARCHAR2)
IS
BEGIN
dbms_output.put_line(parm_head);
WHILE i IS NOT NULL
LOOP
dbms_output.put_line(i ||' : '|| Stu(i));
i := Stu.NEXT(i);
END LOOP;
dbms_output.put_line('________________');
END;
BEGIN
print_item('First:"');
i := Stu.FIRST();
Stu(2) := 'kai';
print_item('Seccend:');
i := Stu.FIRST();
Stu := People('Wu','Gu','Text','helo');
print_item('Three:');
END;
TABLE and VARRAY are discrete in memory allocation, that is, subscript values can be spaced such as Stu (1), Stu (3)... Wait. [VARRAY is fixed size, Table can dynamically grow its length] [3]
Table has another usage (I understand it as another usage) [associative array] [1]:
Dynamic arrays, which do not have constructors, have a value if the definition needs to be initialized manually:
DECLARE
TYPE People
IS
TABLE OF VARCHAR2(23) INDEX BY PLS_INTEGER;
Stu People;
i PLS_INTEGER := Stu.FIRST;
PROCEDURE print_item(
parm_head VARCHAR2)
IS
BEGIN
dbms_output.put_line(parm_head);
WHILE i IS NOT NULL
LOOP
dbms_output.put_line(i ||' : '|| Stu(i));
i := Stu.NEXT(i);
END LOOP;
dbms_output.put_line('________________');
END;
BEGIN
Stu(1) := 'Yang';
Stu(2) := 'Wang';
Stu(3) := 'Xhang';
Stu(4) := 'Li';
print_item('First:"');
i := Stu.FIRST();
Stu(2) := 'kai';
print_item('Seccend:');
i := Stu.FIRST();
-- Stu := People('Wu','Gu','Text','helo'); --No constructor
print_item('Three:');
END;
A good way to initialize AssociatIve array is to initialize it with a function, which can be done in a package.
Package:
--*Baotou*
CREATE OR REPLACE PACKAGE My_Types IS
TYPE My_AA IS TABLE OF VARCHAR(20) INDEX BY PLS_INTEGER;
FUNCTION Init_My_AA RETURN My_AA;
END My_Types;
In this package, an associative array My_AA and a function for initialization are defined.
Enclaves
CREATE OR REPLACE PACKAGE BODY My_Types IS
FUNCTION Init_My_AA RETURN My_AA IS
ret My_AA;
BEGIN
ret(1) := 'HOW';
ret(2) := 'ARE';
ret(3) := 'YOU';
RETURN ret;
END Init_My_AA;
END My_Types;
Program package, the name of the package must be the same as that declared in the package header. The initialization of array My_AA is realized in the package.
Test call
DECLARE
v My_Types.My_AA := My_Types.Init_My_AA();
Idx PLS_INTEGER := v.FIRST();
PROCEDURE print_my_aa(my_ar My_Types.My_AA) IS
BEGIN
IF my_ar.COUNT() = 0 THEN
dbms_output.put_line('empty');
RETURN;
END IF;
FOR i IN my_ar.FIRST() .. my_ar.COUNT() LOOP
dbms_output.put_line(my_ar(i));
END LOOP;
END print_my_aa;
BEGIN
print_my_aa(v);
dbms_output.put_line(' Counts : ' || v.Count());
END;
Create an implicit code block to call, [Note] [2] When declaring, use the package name. Variable name format, as well as when calling the initialization function. In the example above, a stored procedure is used to print the results.
When assignment statements are used to assign values, a set can also be assigned to an existing set. But if you have the same data type, you can't have the same element type.
DECLARE
TYPE pro IS VARRAY(6) OF VARCHAR2(12);
TYPE pro_1 IS VARRAY(6) oF VARCHAR2(12);
group1 pro := pro('how', 'are', 'you');
group2 pro;
group3 pro_1 := pro_1('Just', 'So', 'So');
BEGIN
group2 := group1;
group2 := group3;
END;
ORA-06550: The first 11 That's ok, The first 13 column:
PLS-00382: Expression type error
ORA-06550: The first 11 That's ok, The first 3 column:
PL/SQL: Statement ignored
Above, the group2 and group3 element types are the same, but the data types redefined by type are different, resulting in exceptions.
Variables of type Conllection can also declare a called array (two-dimensional array):
DECLARE
TYPE t1 IS VARRAY(10) OF VARCHAR2(23);
TYPE nt1 IS VARRAY(10) OF t1;
va t1 := t1('hello', 'where', 'are', 'you', 'from');
nva nt1 := nt1(va,
t1('I`m', 'KanKan', 'What`s'),
t1('Today', 'Before', 'Yesterday'),
va);
PROCEDURE print_nt1(parm_nt1 nt1) IS
BEGIN
IF parm_nt1 IS NULL THEN
dbms_output.put_line('NULL');
RETURN;
ELSIF parm_nt1.COUNT() = 0 THEN
dbms_output.put_line('empty');
RETURN;
ELSE
FOR i IN nva.FIRST() .. nva.COUNT() LOOP
FOR j IN nva(i).FIRST() .. nva(i).COUNT() LOOP
dbms_output.put(' ' || nva(i) (j) || ' ');
END LOOP;
dbms_output.put_Line('');
END LOOP;
END IF;
END print_nt1;
BEGIN
dbms_output.put_line('-------------------START BEFORE--------------------------');
print_nt1(nva);
dbms_output.put_line('--------------------EDN AFTER----------------------------');
nva.EXTEND();
nva(nva.COUNT) := va;
print_nt1(nva);
dbms_output.put_line(nva.COUNT);
END;
Create a two-dimensional array with access similar to C. If you need to expand, you can use the keyword [EXTEND][1], such as after EXTEND above, the length of the array is + 1.
Stored procedures, cursors, Nest Table
Demonstrate with Implicit Code Blocks:
Familiar with grammar:
DECLARE
Idx PLS_INTEGER := 0;
--Definition record
TYPE re_emp
IS
RECORD
(
t_name EMP.ENAME%TYPE ,
t_mgr EMP.MGR%TYPE); -- Define a record Used to store cursor values
--Definition table
type tb_emp
IS
TABLE OF re_emp;
-- Define variables
emps tb_emp; -- Definition tableļ¼ Keep multiple records
--cursor
CURSOR cur(num NUMBER)
IS
SELECT ename ,MGR FROM emp WHERE sal < num; -- Define a cursor to extract qualified records from the table
--stored procedure
PROCEDURE pro_search_emps(
t_num IN NUMBER,
t_es OUT tb_emp )
IS
es re_emp; -- Define temporary record
BEGIN
dbms_output.put_line('______ procedure begin _____');
dbms_output.put_line('t_num : '|| t_num);
t_es := tb_emp(); -- Initialization table Otherwise there will be Exception
FOR es IN cur(t_num) -- to Table Add data (1)
LOOP
t_es.EXTEND(); -- again Table Add one at the end NULL value
Idx := Idx +1;
t_es(Idx) := es;
END LOOP;
END pro_search_emps; --Stored procedures are defined to Table Add data to
BEGIN
pro_search_emps(13354,emps);
IF emps IS NOT NULL THEN
Idx := emps.FIRST;
WHILE Idx IS NOT NULL
LOOP
dbms_output.put_line(emps(Idx).t_name);
Idx := emps.NEXT(Idx);
END LOOP;
ELSE
dbms_output.put_line('emps is Empty');
END IF;
END;
Purpose:
Define a Record to store data taken from Cursor. A Table is defined to store multiple records.
Be careful:
- You must initialize variables before you use them. Define variables as much as possible before you define types.
If you change the for loop in Demo to white mode, the code is as follows:
OPEN cur(t_num);
FETCH cur INTO es;
IF cur%notfound THEN
dbms_output.put_line('No information');
RETURN;
ELSE
WHILE cur%found
LOOP
t_es.EXTEND();
Idx := Idx +1;
t_es(Idx) := es;
FETCH cur INTO es;
END LOOP;
END IF;
CLOSE cur;
Replace the for <var> in <Cursor> loop <statement> end loop with the above while mode. Privately thought: while mode is easier to understand, but for is shorter.
Mark's done...