Presentation is loading. Please wait.

Presentation is loading. Please wait.

1 Theory, Practice & Methodology of Relational Database Design and Programming Copyright © Ellis Cohen 2002-2008 Using Data Structures in Embedded Programs.

Similar presentations


Presentation on theme: "1 Theory, Practice & Methodology of Relational Database Design and Programming Copyright © Ellis Cohen 2002-2008 Using Data Structures in Embedded Programs."— Presentation transcript:

1 1 Theory, Practice & Methodology of Relational Database Design and Programming Copyright © Ellis Cohen 2002-2008 Using Data Structures in Embedded Programs These slides are licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.5 License. For more information on how you may use them, please see http://www.openlineconsult.com/db

2 2 © Ellis Cohen 2001-2008 Overview of Lecture Intermediate Data Structures PL/SQL Varying Arrays PL/SQL Associative Arrays

3 3 © Ellis Cohen 2001-2008 Intermediate Data Structures

4 4 © Ellis Cohen 2001-2008 General Modularized Query Example BEGIN … -- Iterate through a data structure … -- defined in the data tier … -- Use each row to build part of the result … -- to be displayed EXCEPTION WHEN OTHERS THEN plerr(); END; Provide an iterable data structure which –hides the detailed structure of the underlying tables –make it possible to iterate through the data structure to get the number of employees in each department who have a specified job ShowDeptsByJob( :job ) Data Tier Code

5 5 © Ellis Cohen 2001-2008 Providing Intermediate Results There are a variety of ways that the data tier can generate iterable data structures for use in user operation code –Views –Temporary Tables –Cursors –XML –Data Collection Structures (e.g. Arrays)

6 6 © Ellis Cohen 2001-2008 Using Views BEGIN FOR erec IN (SELECT deptno, knt FROM DeptsByJobView WHERE job = :job) LOOP … -- use erec to build … -- part of the result to be displayed END LOOP; EXCEPTION WHEN OTHERS THEN plerr(); END; CREATE VIEW DeptsByJobView AS SELECT job, deptno, count(*) AS knt FROM Emps GROUP BY job, deptno ShowDeptsByJob( :job )

7 7 © Ellis Cohen 2001-2008 Why Use Other Approaches? Use other approaches for intermediate data transfers when Views cannot be used –Suppose the result requires that an external service be used to obtain some or all of the result Views are too relational –When it is useful to build and return more complex data structures Views are more expensive –The result is incrementally built based on previous requests, and can be maintained incrementally Views provide too much information –The view provides information about all depts, not just those with the job specified (can be solved by using cursors)

8 8 © Ellis Cohen 2001-2008 Using Cursors BEGIN FOR erec IN (SELECT deptno, knt FROM EmpPkg.DeptsByJobCursor( :job ) LOOP … -- use erec to build … -- part of the result to be displayed END LOOP; EXCEPTION WHEN OTHERS THEN plerr(); END; CURSOR DeptsByJobsCurs( theJob varchar ) IS SELECT deptno, count(*) AS knt FROM Emps WHERE job = theJob GROUP BY deptno; ShowDeptsByJob( :job ) Defined in EmpPkg

9 9 © Ellis Cohen 2001-2008 Using a Temporary Tables BEGIN EmpPkg.FillDeptsByJob( :job ); FOR erec IN (SELECT deptno, knt FROM DeptKnts) LOOP … -- use erec to build … -- part of the result END LOOP; EXCEPTION WHEN OTHERS THEN plerr(); END; ShowDeptsByJob( :job ) Fill the Temporary Table Use it

10 10 © Ellis Cohen 2001-2008 Defining & Filling Temporary Tables CREATE GLOBAL TEMPORARY TABLE DeptKnts ( deptno int, knt int ); PROCEDURE FillDeptsByJob( theJob varchar ) IS BEGIN INSERT INTO DeptKnts SELECT deptno, count(*) AS knt FROM Emps WHERE job = theJob GROUP BY deptno; END; In EmpPkg

11 11 © Ellis Cohen 2001-2008 Using a Local Table DECLARE deptknts DeptKntTbl; BEGIN FOR erec IN (SELECT deptno, knt FROM TABLE(GetDeptsByJob( :job ))) LOOP … -- use erec to build part of the result END LOOP; EXCEPTION WHEN OTHERS THEN plerr(); END; Returns a local table ShowDeptsByJob( :job )

12 12 © Ellis Cohen 2001-2008 Defining & Filling a Local Table TYPE DeptKntType IS OBJECT ( deptno int, knt int ); TYPE DeptKntTbl IS TABLE OF DeptKntType; FUNCTION GetDeptsByJob( theJob varchar ) RETURN DeptKntTbl IS deptknts DeptKntTbl := DeptKntTbl(); BEGIN FOR aRec IN (SELECT deptno, count(*) AS knt FROM Emps WHERE job = theJob GROUP BY deptno) LOOP deptknts.extend(); deptknts( deptknts.last ) := aRec; END LOOP; END; In EmpPkg

13 13 © Ellis Cohen 2001-2008 Using an Array DECLARE deptknts EmpPkg.DeptKntList; BEGIN deptknts := EmpPkg.GetDeptsByJob( :job ); FOR i IN 1..deptknts.count LOOP -- use deptknts(i) to build part of the result END LOOP; EXCEPTION WHEN OTHERS THEN plerr(); END; Returns an associative or varying array ShowDeptsByJob( :job )

14 14 © Ellis Cohen 2001-2008 Defining & Filling a Varying Array TYPE DeptKntRec IS RECORD ( deptno int, knt int ); TYPE DeptKntList IS VARRAY(1000) OF DeptKntRec FUNCTION GetDeptsByJob( theJob varchar ) RETURN DeptKntList IS deptknts DeptKntList := DeptKntList(); BEGIN FOR aRec IN (SELECT deptno, count(*) AS knt FROM Emps WHERE job = theJob GROUP BY deptno) LOOP deptknts.extend(); deptknts( deptknts.last ) := aRec; END LOOP; END; In EmpPkg

15 15 © Ellis Cohen 2001-2008 Defining & Filling an Associative Array TYPE DeptKntRec IS RECORD ( deptno int, knt int ); TYPE DeptKntList IS TABLE OF DeptKntRec INDEX BY BINARY_INTEGER; FUNCTION GetDeptsByJob( theJob varchar ) RETURN DeptKntList IS deptknts DeptKntList; BEGIN FOR aRec IN (SELECT deptno, count(*) AS knt FROM Emps WHERE job = theJob GROUP BY deptno) LOOP deptknts( deptknts.count +1 ) := aRec; END LOOP; END; In EmpPkg

16 16 © Ellis Cohen 2001-2008 Collection Comparisons VARRAY Local Table Associative Array Str IndexNO YES AutoGrowNO YES SparseNO YES UnboundedNOYES QueryableNOYESNO Store in DBYES NO Ordered in DBYESNO

17 17 © Ellis Cohen 2001-2008 PL/SQL Varying Arrays

18 18 © Ellis Cohen 2001-2008 Varying Arrays Arrays indexed from 1 up to a varying length, with a specified limit Values can be almost any type: simple types, records, even other collections In a single array, the values have a single declared type TYPE EmpAryType IS VARRAY(10) OF emp%ROWTYPE 10 20 30 123123 Can grow to 10 slots

19 19 © Ellis Cohen 2001-2008 Varying Arrays DECLARE TYPE int10 IS VARRAY(10) OF int; ints int10 := int10( 10, 20, 30 ); BEGIN FOR i in 1..ints.count LOOP pl( i || ': ' || ints(i) ); END LOOP; END; 10 20 30 123123

20 20 © Ellis Cohen 2001-2008 Extending VARRAYs DECLARE TYPE int10 IS VARRAY(10) OF int; ints int10 := int10(); BEGIN FOR i IN 1..ints.limit LOOP ints.extend(); ints(i) := 10*i; pl( i || ': ' || ints(i) ); END LOOP; END;

21 21 © Ellis Cohen 2001-2008 Using a Varying Array DECLARE deptknts EmpPkg.DeptKntList; BEGIN deptknts := EmpPkg.GetDeptsByJob( :job ); FOR i IN 1..deptknts.count LOOP -- use deptknts(i) to build part of the result END LOOP; EXCEPTION WHEN OTHERS THEN plerr(); END; Returns a varying array ShowDeptsByJob( :job )

22 22 © Ellis Cohen 2001-2008 Defining & Filling a Varying Array TYPE DeptKntRec IS RECORD ( deptno int, knt int ); TYPE DeptKntList IS VARRAY(1000) OF DeptKntRec FUNCTION GetDeptsByJob( theJob varchar ) RETURN DeptKntList IS deptknts DeptKntList := DeptKntList(); BEGIN FOR aRec IN (SELECT deptno, count(*) AS knt FROM Emps WHERE job = theJob GROUP BY deptno) LOOP deptknts.extend(); deptknts( deptknts.last ) := aRec; END LOOP; END; In EmpPkg

23 23 © Ellis Cohen 2001-2008 PL/SQL Associative Arrays

24 24 © Ellis Cohen 2001-2008 Integer Arrays Associates a value with an integer index, and later allows the value to be looked up by providing the index SMITH ALLEN WARD 123123 key value Values can be almost any type: simple types, records, even other collections In a single array, the values have a single declared type … TYPE strHashType IS TABLE OF VARCHAR(30) INDEX BY BINARY_INTEGER; TYPE empHashType IS TABLE OF emp%ROWTYPE INDEX BY BINARY_INTEGER;

25 25 © Ellis Cohen 2001-2008 Associative Arrays as Hashtables Associates a value with an arbitrary integer key, and later allows the value to be looked up by providing the key SMITH ALLEN WARD 7369 7521 7499 key value Values can be almost any type: simple types, records, even other collections In a single array, the values have a single declared type … TYPE strHashType IS TABLE OF VARCHAR(30) INDEX BY BINARY_INTEGER; TYPE empHashType IS TABLE OF emp%ROWTYPE INDEX BY BINARY_INTEGER;

26 26 © Ellis Cohen 2001-2008 Integer-Indexed Associative Arrays DECLARE TYPE empHashType IS TABLE OF emp%ROWTYPE INDEX BY BINARY_INTEGER; emptbl empHashType; i int; BEGIN FOR aRec IN (SELECT * FROM Emps) LOOP emptbl( aRec.empno ) := aRec; END LOOP; i := emptbl.first(); WHILE (i is not null) LOOP pl( i || ': ' || emptbl(i).ename ); i := emptbl.next(i); END LOOP; END; emp1 emp2 emp3 7369 7521 7499 emptbl … Use the employee number as the key!

27 27 © Ellis Cohen 2001-2008 String-Indexed Associative Arrays DECLARE TYPE empHashType IS TABLE OF emp%ROWTYPE INDEX BY VARCHAR2(30); emptbl empHashType; nm VARCHAR2(30); BEGIN FOR aRec IN (SELECT * FROM Emps) LOOP emptbl( aRec.ename ) := aRec; END LOOP; nm := emptbl.first(); WHILE (nm is not null) LOOP pl( emptbl(nm).empno || ': ' || nm ); nm := emptbl.next(nm); END LOOP; END; emp1 emp2 emp3 SMITH ALLEN WARD emptbl … Use the employee name as the key!

28 28 © Ellis Cohen 2001-2008 Associative Array Exercise Suppose TYPE empHashType IS TABLE OF emp%ROWTYPE INDEX BY BINARY_INTEGER; emptbl empHashType; TYPE jobHashType IS TABLE OF emp%ROWTYPE INDEX BY VARCHAR2(30); jobtbl jobHashType; Suppose that emptbl contains a collection of employees indexed by their employee number. Write code so that jobtbl (which is empty) is filled with a a collection of employees, one for each job. In fact, jobtbl's index is a job title, and jobtbl(j) will hold the highest paid employee who has job j. Note that tbl.exists(val) is true if tbl contains an element whose index is val. Hint: This can be done by looping once through emptbl, and deciding what to do with each employee.

29 29 © Ellis Cohen 2001-2008 Associative Array Exercise Answer DECLARE empnum pls_integer; eJob emp.job%TYPE; BEGIN empnum := emptbl.first(); WHILE (empnum is not null) LOOP ejob := emptbl(empnum).job; IF (NOT jobtbl.exists(ejob)) OR emptbl(empnum).sal > jobtbl(ejob).sal THEN jobtbl(ejob) := emptbl(empnum); END IF; empnum := emptbl.next(empnum); END LOOP; END; Short- circuited boolean operator evaluation

30 30 © Ellis Cohen 2001-2008 DECLARE TYPE IntList IS TABLE OF int INDEX BY BINARY_INTEGER; empnums IntList; BEGIN FOR aRec IN (SELECT * FROM Emps) LOOP empnums( empnums.count +1 ) := aRec.empno; END LOOP; FOR i IN 1..empnums.count LOOP pl( empnums(i) ); END LOOP; END; Associative Arrays as Lists empno1 empno2 empno3 123123 … empnums

31 31 © Ellis Cohen 2001-2008 Using an Associative Array DECLARE deptknts EmpPkg.DeptKntList; BEGIN deptknts := EmpPkg.GetDeptsByJob( :job ); FOR i IN 1..deptknts.count LOOP -- use deptknts(i) to build part of the result END LOOP; EXCEPTION WHEN OTHERS THEN plerr(); END; Returns an associative array ShowDeptsByJob( :job )

32 32 © Ellis Cohen 2001-2008 Defining & Filling an Associative Array TYPE DeptKntRec IS RECORD ( deptno int, knt int ); TYPE DeptKntList IS TABLE OF DeptKntRec INDEX BY BINARY_INTEGER; FUNCTION GetDeptsByJob( theJob varchar ) RETURN DeptKntList IS deptknts DeptKntList; BEGIN FOR aRec IN (SELECT deptno, count(*) AS knt FROM Emps WHERE job = theJob GROUP BY deptno) LOOP deptknts( deptknts.count +1 ) := aRec; END LOOP; END; In EmpPkg


Download ppt "1 Theory, Practice & Methodology of Relational Database Design and Programming Copyright © Ellis Cohen 2002-2008 Using Data Structures in Embedded Programs."

Similar presentations


Ads by Google