Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
ODTUG Kaleidoscope
June 18 21, 2007
Pre-conference Hands-on Training - June 16 17
Everything you need to know about collections, but were afraid to ask
Steven Feuerstein
PL/SQL Evangelist Quest Software steven.feuerstein@quest.com
Copyright 2000-2006 Steven Feuerstein - Page 2
How to benefit most from this seminar Watch, listen, ask questions. Download the training materials and supporting scripts:
http://oracleplsqlprogramming.com/resources.html "Demo zip": all the scripts I run in my class available at http://oracleplsqlprogramming.com/downloads/demo.zip
filename_from_demo_zip.sql
Use these materials as an accelerator as you venture into new territory and need to apply new techniques. Play games! Keep your brain fresh and active by mixing hard work with challenging games MasterMind and Set (www.setgame.com)
Copyright 2000-2006 Steven Feuerstein - Page 4
PL/SQL Collections
Collections are single-dimensioned lists of information, similar to 3GL arrays. They are an invaluable data structure.
All PL/SQL developers should be very comfortable with collections and use them often.
What is a collection?
1 abc 2 def 3 sf 4 q
...
22 rrr
23 swq
A collection is an "ordered group of elements, all of the same type." (PL/SQL User Guide and Reference)
That's a very general definition; lists, sets, arrays and similar data structures are all types of collections. Each element of a collection may be addressed by a unique subscript, usually an integer but in some cases also a string. Collections are single-dimensional, but you can create collections of collections to emulate multi-dimensional structures.
Copyright 2000-2006 Steven Feuerstein - Page 7
Serve up complex datasets of information to nonPL/SQL host environments using table functions. Dramatically improve multi-row querying, inserting, updating and deleting the contents of tables.
Combined with BULK COLLECT and FORALL....
Emulate bi-directional cursors, which are not yet supported within PL/SQL.
Copyright 2000-2006 Steven Feuerstein - Page 8
Sparse
Data does not have to be stored in consecutive rows, as is required in traditional 3GL arrays and VARRAYs.
Part of object model, requiring initialization. Is always dense initially, but can become sparse after deletes.
Can be defined as a schema level type and used as a relational table column type.
Copyright 2000-2006 Steven Feuerstein - Page 11
nested_table_example.sql
About Varrays
Has a maximum size, associated with its type.
Can adjust the size at runtime in Oracle10g R2.
Part of object model, requiring initialization. Is always dense; you can only remove elements from the end of a varray. Can be defined as a schema level type and used as a relational table column type.
varray_example.sql
Use the NOCOPY hint to reduce overhead of passing collections in and out of program units. Encapsulate or hide details of collection management. Don't always fill collections sequentially. Think about how you need to manipulate the contents. Try to read a row that doesn't exist, and Oracle raises NO_DATA_FOUND.
Copyright 2000-2006 Steven Feuerstein - Page 15
mysess.pkg sess2.sql nocopy*.*
Application
PGA
Function
Application Requests Data
Subsequent accesses
Data found in cache. Database is not needed.
Database
Application
PGA
Function
Application Requests Data
emplu.pkg emplu.tst
Oracle9i Release 2
Prior to Oracle9iR2, you could only index by BINARY_INTEGER. You can now define the index on your associative array to be:
Any sub-type derived from BINARY_INTEGER VARCHAR2(n), where n is between 1 and 32767 %TYPE against a database column that is consistent with the above rules A SUBTYPE against any of the above.
This means that you can now index on string values! (and concatenated indexes and...)
Copyright 2000-2006 Steven Feuerstein - Page 17
Oracle9i Release 2
All of the following are now valid TYPE declarations in Oracle9i Release 2
You cannot use %TYPE against an INTEGER column, because INTEGER is not a subtype of BINARY_INTEGER.
DECLARE TYPE TYPE TYPE TYPE TYPE TYPE TYPE
INDEX BY BINARY_INTEGER; INDEX BY PLS_INTEGER; INDEX BY POSITIVE; INDEX BY NATURAL; INDEX BY VARCHAR2(64); INDEX BY VARCHAR2(32767); INDEX BY employee.last_name%TYPE; TYPE array_t8 IS TABLE OF NUMBER INDEX BY types_pkg.subtype_t;
IS IS IS IS IS IS IS
OF OF OF OF OF OF OF
Specifying a row via a string takes some getting used to, but if offers some very powerful advantages.
Copyright 2000-2006 Steven Feuerstein - Page 19
Emulate the various indexing mechanisms (primary key, unique indexes) with collections.
Demonstration package: assoc_array5.sql Generate a caching package: genaa.sql genaa.tst Comparison of performance of different approaches: vocab*.*
PROCEDURE mark_as_used (value_in IN maxvarchar2_t) IS BEGIN g_names_used ( value_in ) := TRUE; END mark_as_used; END string_tracker; Copyright 2000-2006 Steven Feuerstein - Page 21
string_tracker1.*
Oracle9i
Multi-level Collections
Prior to Oracle9i, you could have collections of records or objects, but only if all fields were scalars.
A collection containing another collection was not allowed.
Now you can create collections that contain other collections and complex types.
Applies to all three types of collections.
Let's extend the first version to support multiple lists by using a string-indexed, multilevel collection.
A list of lists....
string_tracker2.*
Oracle10g
Oracle10g
Oracle10g
END;
Turbo-charged SQL with BULK COLLECT and FORALL Improve the performance of multi-row SQL operations by an order of magnitude or more with bulk/array processing in PL/SQL!
CREATE OR REPLACE PROCEDURE upd_for_dept ( dept_in IN employee.department_id%TYPE ,newsal_in IN employee.salary%TYPE) IS CURSOR emp_cur IS SELECT employee_id,salary,hire_date FROM employee WHERE department_id = dept_in; BEGIN FOR rec IN emp_cur LOOP UPDATE employee SET salary = newsal_in WHERE employee_id = rec.employee_id; END LOOP; END upd_for_dept;
Copyright 2000-2006 Steven Feuerstein - Page 30
Conventional Bind
Oracle server
PL/SQL Runtime Engine
PL/SQL block
FOR rec IN emp_cur LOOP UPDATE employee SET salary = ... WHERE employee_id = rec.employee_id; END LOOP;
SQL Engine
SQL Engine
bulktiming.sql bulk_rowcount.sql
Declare a collection of records to hold the queried data. Use BULK COLLECT to retrieve all rows.
bulkcoll.sql
Use the LIMIT clause with the INTO to manage the amount of memory used with the BULK COLLECT operation.
WARNING! BULK COLLECT will not raise NO_DATA_FOUND if no rows are found. Best to check contents of collection to confirm that something was retrieved.
bulklimit.sql
Bulk collects:
Can be used with implicit and explicit cursors Collection is always filled sequentially, starting at row 1.
Copyright 2000-2006 Steven Feuerstein - Page 36
emplu.pkg cfl_to_bulk*.*
Combined with REF CURSORs, you can now more easily transfer data from within PL/SQL to host environments.
Java, for example, works very smoothly with cursor variables
Copyright 2000-2006 Steven Feuerstein - Page 37
Simple table function example Return a list of names as a nested table, and then call that function in the FROM clause.
CREATE OR REPLACE FUNCTION lotsa_names ( base_name_in IN VARCHAR2, count_in IN INTEGER ) RETURN names_nt IS retval names_nt := names_nt (); BEGIN retval.EXTEND (count_in); FOR indx IN 1 .. count_in LOOP retval (indx) := base_name_in || ' ' || indx; END LOOP; RETURN retval; END lotsa_names;
SELECT column_value FROM TABLE ( lotsa_names ('Steven' , 100)) names; COLUMN_VALUE -----------Steven 1 ... Steven 100
tabfunc_scalar.sql
tabfunc_streaming.sql
tabfunc_streaming.sql
Pipelined functions allow you to return data iteratively, asynchronous to termination of the function.
As data is produced within the function, it is passed back to the calling process/query.
RETURN...nothing at all!
Collections don't start coding without them. It is impossible to write modern PL/SQL code, taking full advantage of new features, unless you use collections.
From array processing to table functions, collections are required.
Today I offer this challenge: learn collections thoroughly and apply them throughout your backend code.
Your code will get faster and in many cases much simpler than it might have been (though not always!).
Copyright 2000-2006 Steven Feuerstein - Page 47
OPP 2007
February 28 March 1, 2007 San Mateo Marriott San Mateo, California
ODTUG Kaleidoscope
June 18 21, 2007
Pre-conference Hands-on Training - June 16 17