SQL Games We Can Play in PLSQL
SQL Games We Can Play in PLSQL
inside PL/SQL
Steven Feuerstein
[email protected]
Quest Software
name of file
Copyright 2000-2006 Steven Feuerstein - Page 2
Let the Games Begin!
DECLARE
Declare a TYPE employees_aat IS TABLE OF employees%ROWTYPE
collection of INDEX BY BINARY_INTEGER;
records to hold
l_employees employees_aat;
the queried data.
BEGIN
SELECT *
BULK COLLECT INTO l_employees
Use BULK FROM employees;
COLLECT to
retrieve all rows. FOR indx IN 1 .. l_employees.COUNT
LOOP
process_employee (l_employees(indx));
Iterate through the END LOOP;
END;
collection
contents with a
loop.
bulkcoll.sql
Copyright 2000-2006 Steven Feuerstein - Page 8
Limit the number of rows returned by
BULK COLLECT
CREATE OR REPLACE PROCEDURE bulk_with_limit
(deptno_in IN dept.deptno%TYPE)
IS Use the LIMIT clause with the
CURSOR emps_in_dept_cur IS INTO to manage the amount
SELECT *
FROM emp
of memory used with the
WHERE deptno = deptno_in; BULK COLLECT operation.
PROCEDURE update_emps (
col_in IN VARCHAR2, empnos_in IN numList) IS
enames NameList;
BEGIN
FORALL indx IN empnos_in.FIRST .. empnos_in.LAST
EXECUTE IMMEDIATE
'UPDATE emp SET ' || col_in || ' = ' || col_in
|| ' * 1.1 WHERE empno = :1
RETURNING ename INTO :2'
USING empnos_in (indx ) Notice that empnos_in
RETURNING BULK COLLECT INTO enames; is indexed, but enames
... is not.
END;
Copyright 2000-2006 Steven Feuerstein - Page 11
Oracle9i
Dynamic BULK COLLECT
Now you can even avoid the OPEN FOR and just
grab your rows in a single pass!
CREATE OR REPLACE PROCEDURE fetch_by_loc (loc_in IN VARCHAR2)
IS
TYPE numlist_t IS TABLE OF NUMBER;
TYPE namelist_t IS TABLE OF VARCHAR2 (15);
emp_cv sys_refcursor;
empnos numlist_t;
enames namelist_t;
sals numlist_t;
BEGIN
OPEN emp_cv FOR 'SELECT empno, ename FROM emp_' || loc_in;
FETCH emp_cv BULK COLLECT INTO empnos, enames;
CLOSE emp_cv;
It only DECLARE
TYPE employee_aat IS TABLE OF employee.employee_id%TYPE
processes INDEX BY PLS_INTEGER;
l_employees employee_aat;
the rows TYPE boolean_aat IS TABLE OF BOOLEAN
INDEX BY PLS_INTEGER;
with row l_employee_indices boolean_aat;
numbers BEGIN
l_employees (1) := 7839;
matching l_employees (100) := 7654;
l_employees (500) := 7950;
the defined --
l_employee_indices (1) := TRUE;
rows of the l_employee_indices (500) := TRUE;
--
driving FORALL l_index IN INDICES OF l_employee_indices
DECLARE
It only TYPE employee_aat IS TABLE OF employee.employee_id%TYPE
the content --
l_employee_indices (100) := -77;
of a row in l_employee_indices (200) := 99999999;
--
the driving FORALL l_index IN VALUES OF l_employee_indices
UPDATE employee
array. SET salary = 10000
WHERE employee_id = l_employees (l_index);
END;
RETURN retval;
... tabfunc_scalar.sql
END lotsa_names;
Copyright 2000-2006 Steven Feuerstein - Page 21
Steven 100
Streaming data with table functions
tabfunc_streaming.sql
BEGIN
INSERT INTO tickertable
SELECT *
FROM TABLE (stockpivot (CURSOR (SELECT *
FROM stocktable)));
END;
/
tabfunc_setup.sql
Copyright 2000-2006 Steven Feuerstein - Page 25 tabfunc_pipelined.sql
Enabling Parallel Execution
DECLARE
TYPE book_list_t IS TABLE OF books%ROWTYPE;
my_books book_list_t := book_list_t();
BEGIN
my_books.EXTEND (2);
my_books(1).isbn := '1-56592-335-9';
my_books(1).title := 'ORACLE PL/SQL PROGRAMMING';
my_books(2).isbn := '0-596-00121-5';
my_books(2).title := 'ORACLE PL/SQL BEST PRACTICES';
DECLARE
my_book books%ROWTYPE;
BEGIN
my_book.isbn := '1-56592-335-9';
my_book.title := 'ORACLE PL/SQL PROGRAMMING';
my_book.summary := 'General user guide and reference';
my_book.author := 'FEUERSTEIN, STEVEN AND BILL PRIBYL';
my_book.page_count := 950; -- new page count for 3rd edition
UPDATE books
SET ROW = my_book
WHERE isbn = my_book.isbn;
END;