Advanced Techniques | Pl/Sql | Sql

Achieving PL/SQL Excellence

Oracle PL/SQL Advanced Techniques
Oracle7 thru Oracle8i
Steven Feuerstein
www.StevenFeuerstein.com www.Quest.com www.OReilly.com
and contributions most excellent from Bill Pribyl and Dick Bolz

1/21/2011 Copyright 2001 Steven Feuerstein

PL/SQL Advanced Techniques - page 1

Objective & Outline 

Objective
± Expand your knowledge and awareness of important and new features of the PL/SQL language. 

Outline
± ± ± ± ± ± ± ± Building with Packages (Oracle7+) PL/SQL Collections (Oracle7 and Oracle8+) Cursor Variables (Oracle7 and Oracle8+) Dynamic SQL: DBMS_SQL and Native Dynamic SQL (8i) Calling Java from PL/SQL (Oracle8i) and C (Oracle8) Oracle Advanced Queuing with DBMS_AQ (Oracle8) Managing Large Objects with DBMS_LOB (Oracle8) Other Oracle8i New Features
» Autonomous Transactions (Oracle8i) » Invoker Rights Model (Oracle8i) » Row Level Security: DBMS_RLS

1/21/2011 Copyright 2001 Steven Feuerstein

PL/SQL Advanced Techniques - page 2

Software Used in Training 

PL/Vision: a library of packages installed on top of PL/SQL.
± PL/Vision Lite - use it, copy, change it for free -- unless you build software to be sold commercially. ± Active PL/SQL Knowledge Base: contains PL/Vision Professional, the fully supported and enhanced version. 

Demonstration scripts executed in the training can be found on the RevealNet PL/SQL Pipeline:
± http://www.revealnet.com/Pipelines/PLSQL/index.htm ± Archives surfboard, Miscellaneous, PL/SQL Seminar Files ± See filedesc.doc for a listing of many of the files.
plsql_ides.txt 

The PL/SQL IDE (Integrated Development Environment).
± You no longer have to use SQL*Plus and a crude editor! Choose from among the many listed in plsql_ides.txt.

1/21/2011 Copyright 2001 Steven Feuerstein

PL/SQL Advanced Techniques - page 3

Achieving PL/SQL Excellence

Building with PL/SQL Packages 
 

Overview Initialization section Overloading

1/21/2011 Copyright 2001 Steven Feuerstein

PL/SQL Advanced Techniques - page 4

What is a Package? 

A collection of code elements, from procedures and functions to TYPE, variable and cursor declarations.
± Single-most important structure within PL/SQL, and almost certainly one of the most under-utilized. ± Conceptually very simple, it can take some time to fully grasp the implications and potential of the package. 

The method of choice by Oracle and other software developers for extending the PL/SQL language.
± You will find packages in the database, in Oracle Developer/2000, in Oracle Application Server. 

Let¶s review some of the benefits of packages.
tmr.pkg dbparm.pkg

1/21/2011 Copyright 2001 Steven Feuerstein

PL/SQL Advanced Techniques - page 5

± Instead of writing SQL directly in your programs.pkb  Construct very flexible and usable utilities for developers.pkg 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .page 6 . te_employee. ± Can lead to performance improvements. package-based "component". ± Puts more structure and organization in your body of code. watch. ± There's a big difference between a bunch of separate programs and a coherent. you call the packaged procedures and functions instead.pkg  Improve transaction integrity by hiding data structures behind the package interface.When to Build a Package  Join physically logically-related code. custrules.pkg insga.pks te_employee.

the first time any package element is referenced. Does the package have an init section? yes Run initialization code.Package Initialization  The initialization section is a block of code at the end of the package body that is executed once per session. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . Program references package element the first time in each session.page 7 . no Complete request for packaged element. ± The PL/SQL runtime engine determines when and if this code should be run.

FUNCTION func RETURN BEGIN END.Package Initialization Structure  The initialization section: ± Is defined after and outside of any programs in the package. ± Is not required. ± Confirming that package is properly instantiated. PL/SQL Advanced Techniques . PACKAGE BODY pkg IS PROCEDURE proc IS BEGIN END. ± Can have its own exception handling section. 1/21/2011 Copyright 2001 Steven Feuerstein BEGIN after/outside of any program defined in the pkg. In fact. ± Setting up package data which does not change for the duration of a session.page 8 . most packages you build won't have one.  Useful for: ± Performing complex setting of default or initial values. BEGIN END pkg.

printer FROM user_config WHERE user_id = USER.  Also a package with many design flaws. END sessinit. ± Body contains only initialization section.page 9 1/21/2011 Copyright 2001 Steven Feuerstein .pkg init. 'No profile for ' || USER). defprinter INTO show_lov.tst this user. */ SELECT lov_flag. PACKAGE BODY sessinit IS /* No declared package elements at all! */ BEGIN /* Get user preferences for this user. WHEN OTHERS THEN RAISE_APPLICATION_ERROR (-20000.Configure Session with Init. printer VARCHAR2(60). EXCEPTION WHEN NO_DATA_FOUND THEN /* No record for show_lov := show_toolbar := printer := PACKAGE sessinit IS show_lov CHAR(1). END sessinit. tb_flag. show_toolbar CHAR(1). 'lpt1'. */ 'Y'.. init. 'Y'.. show_toolbar. PL/SQL Advanced Techniques . Section  An unusual package! ± Specification contains only variables.

fmts(11) := 'YYYYMMDD'..Populate Collections  The PL/Vision Date package.. ± This increases the flexibility of the date conversion process. fmts(2) := 'DD-MON-YYYY'. PLVdate. fmts(10) := 'MMDDYYYY'. fmts(12) := 'RRMMDD'. . employs several PL/SQL tables to convert strings and to perform date arithmetic.pkg dates. END dt. fmts(4) := 'MM/DD'. ± The datemgr. Initialization section populates a PL/SQL table.page 10 .pkg file demonstrates the basic technique (and the reliance on an initialization section) used to achieve this flexibility. fmt_count := 12. fmts(9) := 'MM/DD/YYYY'. BEGIN fmts(1) := 'DD-MON-RR'. datemgr.sql 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . fmts(3) := 'DD-MON'.

myproc  Overloading is a critical feature when building comprehensive programmatic interfaces (APIs) or components using packages. ± You can overload modules in any declaration section and in packages.Program Overloading  When you overload programs.page 11 . ± Overloading transfers the "need to know" from the user to the overloaded program. ± If you want others to use your code. you need to make that code as smart and as easy to use as possible. myproc myproc 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . you give two or more programs the same name.

page 12 . Without overloading. ± But Oracle couldn't offer that level of convenience without overloading. number_string := TO_CHAR (10000). date_string := TO_CHAR (SYSDATE.Overloading in PL/SQL Built-ins  PL/SQL uses overloading in many common functions. 'MMDDYY'). 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . ± You just probably never gave it a thought. and took functions like TO_CHAR and TO_DATE totally for granted. you would have to deal with something like this: date_string := TO_CHAR_FROM_DATE (SYSDATE. number_string := TO_CHAR_FROM_NUMBER (10000). 'MMDDYY').

the compiler must be able to distinguish between the two calls at compile-time.  Undistinguishing characteristics: ± Functions differ only in their RETURN datatype. There are two different "compile times": ± 1. When you compile programs that use the overloaded code. ± The programs are of different types: procedure and function. ± Arguments differ only in their mode (IN.How Overloading Works  For two or more modules to be overloaded. ± Their formal parameters differ only in datatype and the datatypes are in the same family.  Distinguishing characteristics: ± The formal parameters of overloaded modules must differ in number. order or datatype family (CHAR vs. ± 2. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . OUT. VARCHAR2 is not different enough). When you compile the package or block containing the overloaded code.page 13 . IN OUT).

PACKAGE param_modes IS PROCEDURE proc1 (val IN VARCHAR2). Only difference is parameter mode.PUT_LINE (only_returns. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . END only_returns. PROCEDURE calc (reg_in IN VARCHAR2).func1 (v_value)).calc ('123'). which one? param_modes. which one? too_similar.page 14 . Only difference is function RETURN type. END too_many_cals. END param_modes.proc1 (v_value). PACKAGE only_returns IS FUNCTION func1 (val IN VARCHAR2) RETURN DATE. PROCEDURE proc1 (val IN OUT VARCHAR2). Parameter data types cause conflict.Examples of Invalid Overloadings PACKAGE too_similar IS PROCEDURE calc (reg_in IN CHAR). FUNCTION func1 (val IN VARCHAR2) RETURN VARCHAR2. which one? DBMS_OUTPUT.

l substitute does an even better job.  Fitting the Program to the User ± To make your code as useful as possible. ± The DBMS_OUTPUT. You use the type of data and not its value to determine which of the overloaded programs should be executed.PUT_LINE procedure illustrates this technique -and the PL/Vision p. not Value ± A less common application of overloading. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . you may construct different versions of the ³same´ program which correspond to different patterns of use. the overloading does not provide a single name for different activities.  Overloading by Type. so much as providing different ways of requesting the same activity. In this case.page 15 .Overload Wherever Possible  Supporting Many Data Combinations ± Apply the same action to different kinds or combinations of data.

PROCEDURE l (char_in IN VARCHAR2. PROCEDURE l (char_in IN VARCHAR2. PROCEDURE l (char_in IN VARCHAR2). date_in IN DATE. YYYY . p.HH:MI:SS PM'). boolean_in IN BOOLEAN). YYYY . allowing the user to pass data to the "display engine" without writing "pre-processing" code. PACKAGE p IS PROCEDURE l (date_in IN DATE. PROCEDURE l (number_in IN NUMBER).A "Classic" Overloaded Package  Many different datatype combinations. number_in IN NUMBER).HH:MI:SS PM'). PL/SQL Advanced Techniques .spb PROCEDURE l (boolean_in IN BOOLEAN). mask_in IN VARCHAR2 := µMonth DD. mask_in IN VARCHAR2 := 'Month DD. END p. PROCEDURE l (char_in IN VARCHAR2.sps p.page 16 1/21/2011 Copyright 2001 Steven Feuerstein .

l ('So what is different?').l (print_report_fl).Advantage of Extended Overloading ‡ Minimal overloading means lots of extra coding..PUT_LINE ('So what is different?'). END IF. DBMS_OUTPUT. 'MM/DD/YY HH:MI:SS')). ELSE DBMS_OUTPUT.l (SYSDATE). PL/SQL Advanced Techniques . p. SQLCODE). 1/21/2011 Copyright 2001 Steven Feuerstein ‡Extended overloadings are more likely to meet user needs. p. IF print_report_fl THEN DBMS_OUTPUT. p.page 17 .PUT_LINE (TO_CHAR (SYSDATE.PUT_LINE ('TRUE').PUT_LINE ('FALSE'). DBMS_OUTPUT. DBMS_OUTPUT..l (SQLERRM.PUT_LINE (SQLERRM || ': ' || TO_CHAR (SQLCODE)). p.

.page 18   1/21/2011 Copyright 2001 Steven Feuerstein . If you take these different circumstances into account when you design your package specification. few developers are considerate enough of their users to try to anticipate their needs. In my experience.and taken completely for granted.Fitting the Program to the User Writing "unnecessary" code? Time to overload!  A single piece of functionality.. ± If you want to write software that is admired. the user of your package can benefit from writing less code. think about the way it will be used. can be applied or needed under very different circumstances. PL/SQL Advanced Techniques . ± Your code is a a more natural "fit" under a variety of requirements. such as "display data" or "create a file". appreciated.

'W'). 'exists. BEGIN fid := UTL_FILE. you have to declare the record to hold the file handle.FCLOSE (fid). sometimes you will want to create a file and then perform additional operations. It just needs to be present.FILE_TYPE. UTL_FILE. END.flg'.  In other words.PUT_LINE (fid. UTL_FILE. ± She doesn't care what's in it. even though you are simply going to close the file immediately after opening it.FOPEN ('tmp/flags'. 'blah'). ± Here is the code required by UTL_FILE: DECLARE fid UTL_FILE. so this is just the way it has to be. right? WRONG! PL/SQL Advanced Techniques .Creating a File for a Quick Touch  Suppose a developer needs to create a file to be used as a "flag" in the operating system. Of course.page 19  1/21/2011 Copyright 2001 Steven Feuerstein .

TO_CHAR (SYSDATE)).pkg PL/SQL Advanced Techniques .ini'. END PLVfile. /* Function */ FUNCTION fcreate (file_in IN VARCHAR2.fcreate ('temp.put_line (fid. line_in IN VARCHAR2 := NULL).flg').FILE_TYPE. custrules. BEGIN fid := PLVfile. v_user). 1/21/2011 Copyright 2001 Steven Feuerstein Use as Function DECLARE fid UTL_FILE.FILE_TYPE. PLVfile.  Overloading of FCreate PACKAGE PLVfile IS /* Procedure */ PROCEDURE fcreate (file_in IN VARCHAR2.Procedure and Function Overloaded  Why not overload a "create file" program so that you can pick the one that most closely fits your situation? Consider the PLVfile package of PL/Vision. Use as Procedure BEGIN PLVfile. END. line_in IN VARCHAR2 := NULL) RETURN UTL_FILE.page 20 .fcreate ('exists.

± Pass a string ³name´ of the datatype. ± Pass a piece of data of the right type. ± For example. when you use DBMS_SQL to set up a dynamic query. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . you must call the DEFINE_COLUMN procedure to define the datatype of the Nth column in the cursor.  There are three ways to accomplish this: ± Don't overload.page 21 . the user does not need to pass data. but the type of data."By-Type" Overloading  In some situations. Define a different program name for each datatype.

2.. 30). 30).. DBMS_SQL. Lotsa typing.DEFINE_VARCHAR2_COLUMN (cur.  Nasty hard-coding. DBMS_SQL..DEFINE_COLUMN (cur.DEFINE_COLUMN (cur. 2..page 22 .. BEGIN DBMS_SQL.DEFINE_INTEGER_COLUMN (cur.. 'STRING'.  Now let's look at two examples of overloading by datatype..func 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .DEFINE_COLUMN ± PLVgen. DBMS_SQL.VARCHAR2_TYPE. Pass a named constant. BEGIN DBMS_SQL. DBMS_SQL. 30). ± DBMS_SQL... 2.  So many program names to remember! Pass a literal value..DEFINE_COLUMN (cur...Options for Specifying Column Type  Don't even bother overloading. 1.NUMBER_TYPE). BEGIN DBMS_SQL. 1). 1. 'NUMBER'). DBMS_SQL.DEFINE_COLUMN (cur. lotsa names.

± To make it easier to accomplish this task. 30). 30). BEGIN DBMS_SQL. you only need to pass a value -. 2. from the perspective of DBMS_SQL.page 23 .DEFINE_COLUMN (cur. 'a'.DEFINE_COLUMN.DEFINE_COLUMN (cur.DEFINE_COLUMN (cur. 2. DBMS_SQL.Defining Dynamic SQL Columns  The DBMS_SQL. v_empno).GET_TIME). DBMS_UTILITY. ± The three code blocks below are equivalent. BEGIN DBMS_SQL. DBMS_SQL.DEFINE_COLUMN (cur. 2. 1.DEFINE_COLUMN (cur.DEFINE_COLUMN procedure defines the datatype of a column. 1. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .DEFINE_COLUMN (cur. 1.any value -. 1). BEGIN DBMS_SQL. v_ename. 30).of the correct type. DBMS_SQL. USER.

Generating Functions by Value  In PLVgen. Any number. SQL> exec plvgen. PACKAGE PLVgen IS PROCEDURE func (name_in IN VARCHAR2. 1) A date function. any string. type_in IN DATE). please! A number function. any date. SYSDATE) SQL> exec plvgen.page 24 . type_in IN VARCHAR2). please! 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . ± The particular value itself is of no importance. the user indicates the type of function to be generated by providing a value. PROCEDURE func (name_in IN VARCHAR2. PROCEDURE func (name_in IN VARCHAR2. type_in IN NUMBER).func ('total_salary'.func ('last_date'. any Boolean will do.

PROCEDURE calc (comp_id_IN IN company. PACKAGE profits IS PROCEDURE calc (comp_id_IN IN NUMBER). END.The Frustrations of Overloading  Watch out! An overloading can compile successfully.  In the above example. PL/SQL Advanced Techniques .comp_id%TYPE). I rely on an anchored type (%TYPE) to establish the datatype of the second calc¶s parameter. ± When I compile profits. but you might later found out that you cannot actually call any of the overloaded programs.page 25 1/21/2011 Copyright 2001 Steven Feuerstein . PL/SQL does not sense a conflict with above overloading even though comp_id is a numeric column.

END. sales. sales.  Can I overload two programs which have parameters that differ only by name.calc_total ('ZONE2'). like calc_totals shown above? ± If not.page 26 . END sales. how would you do it? (Don't peek at the next page!) BEGIN sales.Quiz! Nuances of Overloading PACKAGE sales IS PROCEDURE calc_total (zone_in IN VARCHAR2).calc_total ('NORTHWEST').pkg ? 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . PROCEDURE calc_total (reg_in IN VARCHAR2). why not? ± If so.

estimate_percent=>50). ± You can skip over (not specify values for) any IN parameters that have default values. of named notation include: ± Code is more "self-documenting".submit ( job => v_jobno.page 27 .Using Named Notation <formal parameter name> => <expression>  Explicit association between the formal parameter (the "name") with the actual parameter (the "value").null.''TENK''' || '. DBMS_JOB. interval => 'TRUNC(SYSDATE+1)').'.ANALYZE_OBJECT ' || '(''TABLE''.''LOAD1''.''ESTIMATE''.sql  Advantages 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . That way you don't have to know and pass default values. namednot. next_date => TRUNC (SYSDATE + 1). what => 'DBMS_DDL. This is especially useful when working with infrequently used built-in programs.

originally called PL/SQL tables) ± Nested tables (Oracle8 and above) ± Variable arrays (VARRAYs.page 28 . Three types of collections: ± Index-by tables (Oracle7 only. Oracle8 and above) 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .Achieving PL/SQL Excellence PL/SQL Collections   Collections are single-dimensioned lists of information.

 Emulate bi-directional cursors. Improve query performance by avoiding joins.When to Use Collections  Maintain any kind of list of related information for use in your programs. Build hash tables (custom indexing structures). which are otherwise not supported in PL/SQL Cache data in session-level memory for faster access.page 29     1/21/2011 Copyright 2001 Steven Feuerstein . PL/SQL Advanced Techniques . Avoid mutating table errors in database triggers.

647 » You will not actually create tables this large.Index-By Tables TYPE <table_type> IS TABLE OF <datatype> INDEX BY BINARY_INTEGER.483.  Characteristics of an index-by table: ± Unbounded » Practically speaking. DECLARE TYPE inmem_emp_t IS TABLE OF emp%ROWTYPE INDEX BY BINARY_INTEGER. ± Homogeneous » Data in each row has the same structure.647 to 2. Instead.147. ± Sparse » Data does not have to be stored in consecutive rows of information. this broad range allows you to employ the row number as an intelligent key. ± Available only in PL/SQL 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .147. emp_copy inmem_emp_t.page 30 . Valid row numbers range: -2.483.

children 6306 6412 6810 6904 µBarbara Anne¶ µGary Richard¶ µAdam Russell¶ µLisa Nadezhka¶ datemgr.page 31 .pkg children 6306 6412 6904 µBarbara Anne¶ µGary Richard¶ µLisa Marie¶ children (6810) := µAdam Russell.Index_by Tables TYPE declaration PACKAGE BODY family IS TYPE child_list_type IS TABLE OF VARCHAR2 (30) INDEX BY BINARY_INTEGER. Error: NO_DATA_FOUND 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . Variable declaration children child_list_type. Component Selection kid := children (4). children (6904) := 'Lisa Nadezhka'.

± Unbounded.  Nested table characteristics ± Homogeneous » Each row contains the same structure of data.647 ± Initially dense. Valid row numbers range: 1 to 2. birthdays when_t. DECLARE TYPE when_t IS TABLE OF DATE.page 32 .147. but only with explicit EXTEND requests » Practically speaking. but can become sparse if you DELETE inner rows ± Available both in PL/SQL and SQL (as a column in a table) ± The order of elements is not preserved in the database 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .Nested Tables [CREATE OR REPLACE] TYPE <table_type> IS TABLE OF <datatype> [NOT NULL].483.

page 33 . kids child_table_type) NESTED TABLE kids STORE AS kids_ntab. CREATE TABLE db_family (surname VARCHAR2 (30).sql 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . For ORACLE's use only db_family surname kids BOLZ BOND Eric Thomas Max Richard Barbara Anne Gary Richard Lisa Marie ntdemo.Nested Tables CREATE OR REPLACE TYPE child_table_type IS TABLE OF VARCHAR2 (30).

Maximum value: 2.  Characteristics of variable arrays: ± Homogeneous » Each row contains the same structure of data. salaries numbers_t. ± Available both in PL/SQL and SQL (as a column in a table) » And the order of elements are preserved in the database. DECLARE TYPE numbers_t IS VARRAY (10) OF NUMBER.page 34 . ± Variable arrays are actually stored in the DB table 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .147.483. can be EXTENDed or TRIMmed.647 ± Dense » Never any gaps between defined rows. ± Bounded » Upper limit established when the TYPE is defined.Variable Arrays [CREATE OR REPLACE] TYPE <table_type> IS VARRAY (N) OF <datatype> [NOT NULL].

sql 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . kids child_va_type). db_family surname kids BOLZ BOND 1 Barbara Anne 2 Gary Richard 3 Lisa Marie 1 Eric Thomas 2 Max Richard vademo. CREATE TABLE db_family (surname VARCHAR2 (30).Variable Arrays CREATE OR REPLACE TYPE child_va_type IS VARRAY (8) OF VARCHAR2 (30).page 35 .

or in a PL/SQL declaration section.Defining Collections  First. Best option: package specification. ± For index-by tables. from the TYPE. ± You can declare multiple collections from that TYPE. TYPE integer_vat IS VARRAY(10) OF INTEGER.  Then you declare an instance of that type. TYPE integer_nt IS TABLE OF INTEGER.. . ± For nested tables and VARRAYs.. this can only occur in a PL/SQL declaration section. CREATE OR REPLACE PACKAGE tabtypes IS TYPE integer_ibt IS TABLE OF INTEGER INDEX BY BINARY_INTEGER. END tabtypes. a collection. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .page 36 . you can define the TYPE in the database with a CREATE statement. you define the TYPE of the collection.

owner T.sql 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . all_type_attrs A T.Obtaining Collection Information SELECT FROM WHERE AND AND AND A.type_name IN ('NAMES_VT'.attr_name || ' .' || A. colldd.owner = A.attr_type_name Attributes all_coll_types T.  ALL_COLL_TYPES ± The types you have created (or have access to) in the database  ALL_TYPE_ATTRS ± Attributes of the data type used in the TYPE definition.type_name.owner = USER T.page 37 . ± The code used to define the collection TYPE  There is no information in the data dictionary available for index-by tables. 'TMRS_VT') T.elem_type_name = A.

salaries numbers_t := numbers_t (100. 200. salaries numbers_t := numbers_t (100.Initialize the collection. ± Nested tables and VARRAYs are atomically null. DECLARE TYPE numbers_t IS VARRAY (10) OF NUMBER. salary_history numbers_t). BEGIN CREATE TYPE numbers_t IS VARRAY (10) OF NUMBER. ± Index-by tables are initialized automatically. 200.page 38 1/21/2011 Copyright 2001 Steven Feuerstein . it must be initialized. 300). TYPE defined in PL/SQL TYPE defined in the database Collection used in a table PL/SQL Advanced Techniques . / DECLARE -. BEGIN CREATE TABLE employee_denorm ( employee_id INTEGER. 300). empty when declared. You must initialize them explicitly with a constructor.Initializing Collections  Before you can use a collection.

company_id%TYPE. the datatype for any of the collection types can also be an object. consider putting TYPEs in database or packages. ± Can easily create an index-by table with the same structure as a database table by declaring a record with %ROWTYPE. ± But you cannot have nested composite datatypes.page 39 .Collections of Composites  Starting with Oracle 7. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .3.  Starting with Oracle8. Again. the ³homogeneous´ contents of an index-by table's row can be a record . BEGIN comp_tab(1). Here we have a three step process. DECLARE TYPE comp_rectype IS RECORD (comp_id company. total_rev NUMBER). comp_tab comp_tabtype. TYPE comp_tabtype IS TABLE OF comp_rectype INDEX BY BINARY_INTEGER.comp_id := 1005.

± Instead. ± In an index-by table. etc.page 40 . In this way. ± In almost every case. a row exists in the table only when a value is assigned to that row. ± You should not fill sequentially. it is very similar to a database table. consider using the row value as "smart data" for your application (primary key.).Sparse is Nice  The sparse characteristic of index-by tables and nested tables can be put to good use.  Rows do not have to be defined sequentially. your collections will contain a row's worth of information. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . order by date.  Especially handy when caching data from relational tables in user memory. unless the order in which items are selected is of importance.

page 41 . Initialization section of package 1/21/2011 Copyright 2001 Steven Feuerstein  This package moves the entire contents of the emp table into its corresponding collection.Transferring DB Table to Collection CREATE OR REPLACE PACKAGE psemp IS TYPE emp_tabtype IS TABLE OF emp%ROWTYPE INDEX BY BINARY_INTEGER.empno) := rec. END LOOP. emp_tab emp_tabtype. END. END.pkg psemp.tst  PL/SQL Advanced Techniques . CREATE OR REPLACE PACKAGE BODY psemp IS BEGIN FOR rec IN (SELECT * FROM emp) LOOP emp_tab (rec. Some questions: ± Why would I put this collection table in a package? ± When is the collection loaded with the data? ± What rows in that collection are utilized? psemp.

1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . ± Use the EXISTS method to determine if a row existed. END.  For index-by tables. ± Not necessary for index-by tables. ± For VARRAYs and nested tables. the row exists. BEGIN greedy_ceos(1) := 'Hamilton. / Error -6533! You've got to EXTEND first!  EXTEND before assigning a value to a row.page 42 . you must reference existing rows or a NO_DATA_FOUND exception is raised. / DECLARE greedy_ceos names_t := names_t (). even if you haven't assigned a value explicitly. once extended.Collection Gotchas CREATE TYPE names_t IS TABLE OF VARCHAR2(30). but you must do it for VARRAYs and nested tables. Jordan'.

PUT_LINE ('Data for employee not available.We are OK. ± Pre-extending a large number of rows in advance can improve performance. BEGIN IF salaries.FIRST)).tst  Include a handler for NO_DATA_FOUND or use the EXISTS method to avoid these exceptions. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .Set the value of each new row to the contents of the first row. -.').EXISTS (v_employee_id) THEN -. ELSE DBMS_OUTPUT. salaries(salaries. optional argument.  You can EXTEND one or more rows.page 43 .EXTEND (10.Handling Collection Gotchas BEGIN -.Extend by 10 since I know I will need that many. preextend. ± Assign a default value with a second. salaries. END IF.

EXISTS returns TRUE if the specified row is defined.Collection Methods  Obtain information about the collection COUNT returns number of rows currently defined in the table. ± ± ± ±  Modify the contents of the collection ± DELETE deletes one or more rows from the index-by table. number of elements allowed in a VARRAY. ± EXTEND adds rows to a nested table or VARRAY. ± LIMIT tells you the max. ± TRIM removes rows from a VARRAY. FIRST/LAST return lowest/highest numbers of defined rows.  The built-in package plitblm (PL/sql Index-TaBLe Methods) defines these methods.page 44 1/21/2011 Copyright 2001 Steven Feuerstein . PL/SQL Advanced Techniques . NEXT/PRIOR return the closest defined row after/before the specified row.

FREE_UNUSED_USER_MEMORY. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .Delete all rows myCollection.LAST).DELETE (1400.Delete a range of rows myCollection. -. END. but you may also want to call DBMS_SESSION. DELETE releases memory.DELETE (myCollection.DELETE. 17255).The DELETE Method  You can delete one or more rows from a collection using DELETE: BEGIN -.page 45 .Delete one (the last) row myCollection. -.

Navigating Through Collections 


Use FIRST and NEXT to move from beginning to end. Use LAST and PRIOR to move from end to beginning.
rowind PLS_INTEGER := birthdays.FIRST; -- birthdays.LAST BEGIN LOOP EXIT WHEN rowind IS NULL; DBMS_OUTPUT.PUT_LINE (birthdays(rowind).best_present); rowind := birthdays.NEXT (rowind); -- birthdays.PRIOR END LOOP; END;

1/21/2011 Copyright 2001 Steven Feuerstein

PL/SQL Advanced Techniques - page 46

Using Collections Inside SQL 

Nested tables and VARRAYs can be defined as columns of a table and referenced directly within SQL. You can also apply SQL operations to the contents of nested tables and VARRAYs with these operators:
± THE - Maps a single column value in a single row to a virtual database table ± CAST - Maps a collection of one type to a collection of another type ± MULTISET - Maps a database table to a collection ± TABLE - Maps a collection to a database table  

Index-by tables are programmatic constructs only.
± You cannot make a direct reference to an index-by table in SQL. ± Instead, so do indirectly with a PL/SQL function.

1/21/2011 Copyright 2001 Steven Feuerstein

PL/SQL Advanced Techniques - page 47

Using Collections inside SQL
SELECT column_value FROM TABLE (SELECT children FROM db_family WHERE surname = 'BOLZ'); db_family surname children BOLZ BOND Eric Thomas Max Richard UPDATE TABLE (SELECT children FROM db_family WHERE SURNAME = 'BOLZ) SET column_value = 'Lisa Nadezhka' WHERE column_value = 'Lisa Marie'); db_family surname children BOLZ ...
1/21/2011 Copyright 2001 Steven Feuerstein
PL/SQL Advanced Techniques - page 48

Barbara Anne Gary Richard Lisa Marie

column_value Barbara Anne Gary Richard Lisa Marie

Barbara Anne Gary Richard Lisa Nadezhka

Using the THE Operator 

Use THE to manipulate (retrieve, INSERT, UPDATE, DELETE) contents of a nested table in a database table.
± Can only use with nested tables, not VARRAYs or index-by tables. ± Only accessible from within SQL statements in PL/SQL.
CREATE TYPE action_list_t IS TABLE OF VARCHAR2(100); / CREATE TABLE inflation_beater ( focus_area VARCHAR2(100), activities action_list_t) NESTED TABLE activities STORE AS activities_tab; SELECT VALUE (act) FROM THE (SELECT activities FROM inflation_beater WHERE focus_area = 'FORTUNE 100') act; UPDATE THE (SELECT activities FROM inflation_beater WHERE focus_area = 'FORTUNE 100') SET COLUMN_VALUE = 'DISBAND OSHA' WHERE COLUMN_VALUE = 'SIDESTEP OSHA';

the.sql

1/21/2011 Copyright 2001 Steven Feuerstein

PL/SQL Advanced Techniques - page 49

Using the TABLE and CAST Operators 

Use CAST to convert a collection from one type to another, TABLE to convert a TYPE into a database table.
± Cannot use with index-by tables. ± Useful when you would like to apply SQL operations against a PL/SQL collection (ie, one not stored in a database table).
DECLARE nyc_devolution cutbacks_for_taxcuts := cutbacks_for_taxcuts ('Stop rat extermination programs', 'Fire building inspectors', 'Close public hospitals'); BEGIN DBMS_OUTPUT.PUT_LINE ( 'How to Make the NYC Rich Much, Much Richer:'); FOR rec IN (SELECT COLUMN_VALUE ohmy FROM TABLE (CAST (nyc_devolution AS cutbacks_for_taxcuts))) LOOP DBMS_OUTPUT.PUT_LINE (rec.ohmy); END LOOP; cast.sql END;

1/21/2011 Copyright 2001 Steven Feuerstein

PL/SQL Advanced Techniques - page 50

country FROM bird_habitats bh WHERE bh. query) into a VARRAY or nested table. Retrieves all detail bird_row bird_curs%ROWTYPE. b. DECLARE CURSOR bird_curs IS SELECT b.species) AS country_tab_t) FROM birds b.species = b.genus.species. ± Cannot use with index-by tables.genus AND bh. FETCH bird_curs into bird_row. converting a set of data (table. CAST(MULTISET(SELECT bh. END.sql 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . ± You can use MULTISET to emulate or transform relational joins into collections. view. multiset.page 51 . OPEN bird_curs. with potential client-server performance impact.Using the MULTISET Operator  MULTISET is the inverse of TABLE. information for the BEGIN master in one trip.genus = b.

END. 1/21/2011 Copyright 2001 Steven Feuerstein ibtab_in_sql.sql PL/SQL Advanced Techniques .page 52 . Make accessible in SQL for Oracle8 and below. FUNCTION rowval (indx IN PLS_INTEGER) RETURN DATE IS BEGIN RETURN hiredates (indx). PRAGMA RESTRICT_REFERENCES (rowval. WNPS. WNDS). END. but hide the index-by table structure. END. hiredates date_tab. call functions that retrieve the table's data. CREATE OR REPLACE PACKAGE BODY ibtab IS TYPE date_tab IS TABLE OF DATE INDEX BY BINARY_INTEGER. Instead.  CREATE OR REPLACE PACKAGE ibtab IS FUNCTION rowval (indx IN PLS_INTEGER) RETURN DATE.Referencing IB Tables inside SQL  You can't directly reference an index-by table's contents inside SQL.

page 53 .Examples of Collections in Action  Emulation of bi-directional cursor operations Avoid mutating table problems in database triggers.  1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .

deposit your data in a collection and then provide programs to access that data in the necessary fashion.pkg bidir. Notice that the collection itself is hidden. This is particularly useful (read: efficient) when you need to perform multiple passes against the data.page 54 .  bidir. CREATE OR REPLACE PACKAGE bidir IS /* Iterate through rows in the result set */ PROCEDURE setRow (nth IN PLS_INTEGER). didn't make it!  Instead.nope.tst 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . FUNCTION getRow RETURN employee_plus%ROWTYPE. PROCEDURE prevRow. ± A talked-about feature for Oracle9i -. PROCEDURE nextRow.Bi-Directional Cursor Emulation  Oracle does not yet support the ability to move back and forth (and at random) through a cursor's result set. END.

The Mutating Table Problem  Database triggers can be attached to the SQL statement and/or the individual row operations on a table. Statement Level UPDATE emp SET sal = 1000 UPDATE row 1 Row Level  UPDATE row N Row level triggers cannot query from or change the contents of the table to which it is attached. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . it is "mutating".page 55 . you can use autonomous transactions to relax restrictions associated with queries. So what are you supposed to do when a row-level operation needs to "touch" that table? mutating.sql  Note: in Oracle8i.

A Solution Based on Index-by Tables  Since you cannot perform the processing desired in the row-level trigger. Statement Trigger 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . ± an index-by table is an ideal repository for this reminder list. you have to remember what you needed to do. 1st row trigger fires Nth row trigger fires Writes to list Writes to list Work List (PL/SQL Table)  Process data in the list. you need to defer the action until you get to the statement level.page 56 . If you are going to defer the work.

the rankings must also change to show the new standings for that department only. ± As the sales amount is updated in this table.88 144533. Department ID Salesperson ID Sales Amount Rank 1055 1055 1055 1047  64333 65709 65706 70904 74055. ± We might update more than one department within a statement so we must be able to retain multiple department numbers.25 65011. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .91 109000. we then know which departments to re-rank.page 57 .25 3 1 2 6 "Deferred work" is not only necessary. ± By storing the salesperson¶s department ids as they change. but preferable.An Example: Ranking Salespeople  A table holds the rankings based on the amount of annual sales of salespeople within a department.

sales_amt) BEGIN rank.rank_depts.Trigger Logic Required Row Level Trigger CREATE OR REPLACE TRIGGER Rank_Sales_Rtrg AFTER insert OR update OF sales_amt ON rank_sales FOR EACH ROW WHEN (OLD. ranking. Statement Level Trigger CREATE OR REPLACE TRIGGER Rank_Sales_Strg AFTER INSERT OR UPDATE OR DELETE ON rank_sales BEGIN rank. END.pkg All details of the ranking are hidden in the package body.dept_id). 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . END.add_dept (:new.sales_amt != NEW. Doesn't fire unless the sales_amt is actually changed.page 58 .

PROCEDURE add_dept (dept_id_in IN INTEGER) IS BEGIN IF NOT in_process THEN dept_tab (dept_id_in) := TRUE.page 59 . PROCEDURE rank_depts. Table holds indicator that department needs re-ranking. END rank. END add_dept 1/21/2011 Copyright 2001 Steven Feuerstein Create row to indicate department to be ranked. TYPE dept_tabtype IS TABLE OF BOOLEAN INDEX BY BINARY_INTEGER. PACKAGE BODY rank IS in_process BOOLEAN := FALSE. END IF. PL/SQL Advanced Techniques . dept_tab dept_tabtype.The Ranking Package PACKAGE rank IS PROCEDURE add_dept (dept_id_in IN INTEGER).

END LOOP. END IF. 1/21/2011 Copyright 2001 Steven Feuerstein Avoid recursive execution of logic Row number is department number. perform_ranking (v_deptid). END rank_dept. PL/SQL Advanced Techniques . END rank.DELETE.page 60 . v_deptid := dept_tab. Clean up for next time. dept_tab.FIRST.The Ranking Package. in_process := FALSE. LOOP EXIT WHEN v_deptid IS NULL. Continued PROCEDURE rank_depts IS v_deptid PLS_INTEGER := dept_tab. BEGIN IF NOT in_process THEN in_process := TRUE.NEXT (v_deptid).

Which Collection Type Should I Use?  Index-by tables ± Need to use in both Oracle7 and Oracle8 applications ± Want to take advantage of sparse nature for "intelligent keys". Set of data is relatively small (avoid row chaining).page 61 . You want to use inside SQL.  Nested tables ± You want to store large amounts of persistent data in a column. ± You want to use inside SQL. You don't want to have to worry about sparseness.  VARRAYs ± ± ± ± You want to preserve the order in which elements are stored. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .

Tips for Using Collections 

Wrap access to your collections.
± In many cases, you will want to avoid direct access to (assigning and retrieving) rows in your collections. ± This will give you the flexibility to change your implementation. ± You can also hide complex rules for setting the row number. 

Get creative!
± Don't always fill and use the index-by table sequentially. ± If you can somehow translate your application data to an integer, it can be used as a row number, and therefore offers indexed access. ± Julian date formats and DBMS_UTILITY.GET_HASH_VALUE offer two different methods.

1/21/2011 Copyright 2001 Steven Feuerstein

PL/SQL Advanced Techniques - page 62

Achieving PL/SQL Excellence

Cursor Variables

1/21/2011 Copyright 2001 Steven Feuerstein

PL/SQL Advanced Techniques - page 63

Architecture of Cursor Variables
With Hard-Coded Cursors
Hard-Coded Cursor

With Cursor Variables

PGA

Cursor Variable

Cursor Variable

Result Set

Shared Global Area

Cursor Object

Result Set 

A cursor variable points to an underlying cursor object in the database.
± The cursor object in turns points to (and keeps its place in) a result set. 

The cursor variable can be passed between programs (even between, say, a Java servlet and a PL/SQL stored procedure).
± Static SQL only -- until Oracle8i.
PL/SQL Advanced Techniques - page 64

1/21/2011 Copyright 2001 Steven Feuerstein

Benefits of Cursor Variables 

Share cursor management between programs, even across the client-server divide.
± You don't have to pass the result sets of a cursor in order to allow the client-side program to have direct access to the data in the result set. ± Oracle Developer 2.1 utilizes cursor variables when you choose to construct a "base table block" around stored procedures instead of a database table. 

Share the same code across multiple, different queries.
± Since the cursor name is no longer hard-coded, you can use a single block of code (say, a reporting program) against different queries. ± We will try out this technique at the end of the section.

1/21/2011 Copyright 2001 Steven Feuerstein

PL/SQL Advanced Techniques - page 65

Cursor Variable Example
DECLARE TYPE company_curtype IS REF CURSOR RETURN company%ROWTYPE;
Declare a variable cursor TYPE.

company_curvar company_curtype;

Declare cursor variable based on that type. Declare a record from cursor variable. OPEN cursor variable, specifying the query. FETCH from the cursor variable.

company_rec company_curvar%ROWTYPE; BEGIN OPEN company_curvar FOR SELECT * FROM company;

FETCH company_curvar INTO company_rec;
Close the cursor variable.

CLOSE company_curvar; END;
1/21/2011 Copyright 2001 Steven Feuerstein

PL/SQL Advanced Techniques - page 66

Explicit Cursors and Cursor Variables 

Both hard-coded cursors and cursor variables work with static SQL.
± The SQL is fixed at compile-time. ± The difference is that with cursor variables, you get to decide which static query is opened. 

Many cursor operations are the same:
± Close a variable cursor with the same syntax as that for static cursors. ± Use cursor attributes (%ISOPEN, %FOUND, %NOTFOUND, %ROWCOUNT) with cursor variables (as of Release 2.3). ± Fetch data from the cursor result set through a cursor variable with the same syntax as that of static cursors. 

Let¶s focus on the new and different capabilities of cursor variables.
PL/SQL Advanced Techniques - page 67

1/21/2011 Copyright 2001 Steven Feuerstein

Declaring Cursor Types and Variables 

Cursors are declared in two steps, just like programmerdefined records and PL/SQL tables.
± 1. Define a cursor TYPE -- either "weak" or "strong". ± 2. Define a cursor variable.
DECLARE TYPE weak_curtype IS REF CURSOR; TYPE comp_curtype IS REF CURSOR RETURN company%ROWTYPE; curcmp_new comp_curtype; cur_any weak_curtype; BEGIN
Declare cursor variables from the TYPEs. Declare a STRONG referenced cursor TYPE. Declare a WEAK referenced cursor TYPE.

1/21/2011 Copyright 2001 Steven Feuerstein

PL/SQL Advanced Techniques - page 68

Strong vs. Weak Cursor Types 

A strong (or constrained) cursor type has a defined return data specification.
± Can only reference cursor objects which return the same data specification, which can be any single SQL datatype or any previously defined record structure. ± Datatype mismatches are identified at compile time.

TYPE cur_typ_name IS REF CURSOR [ RETURN return_type ]; TYPE cur_typ_name IS REF CURSOR RETURN emp%ROWTYPE; /* Strong */ 

The weak (or unconstrained) cursor type does not have a RETURN clause.
± It can reference any cursor object, be opened FOR any query. ± Datatype mismatches can only be identified at runtime.

TYPE cur_typ_name IS REF CURSOR; /* Weak */
1/21/2011 Copyright 2001 Steven Feuerstein
PL/SQL Advanced Techniques - page 69

Opening with the Cursor Variable
OPEN cursor_name FOR select_statement; 

When you open a cursor variable (whether of the weak or strong variety), you must provide the SQL query that identifies the result set.
± If the variable has not yet been assigned to cursor object, the OPEN FOR statement implicitly creates an object for the variable. ± If the variable is already pointing to a cursor object, the OPEN FOR reuses the existing object and attaches the new query to that cursor object. 

Remember, the cursor object is nothing more than a memory location.
± It is maintained independently of the query itself.
PL/SQL Advanced Techniques - page 70

1/21/2011 Copyright 2001 Steven Feuerstein

Match Needed BEGIN OPEN emp_curvar FOR SELECT * from emp.  STRONG cursor data specifications must match or be compatible with the structure of the SELECT statement. . ± You can establish the return type based on a database table. a cursor or a programmer-defined record. emp_curvar emp_curtype.Opening with Strong Cursor Types DECLARE TYPE emp_curtype IS REF CURSOR RETURN emp%ROWTYPE.page 71 . END.. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques ..

 A weak cursor TYPE doesn't define the RETURN structure. Verification will take ELSIF get_type_in = µDEPT¶ place at the FETCH. THEN OPEN retval FOR SELECT * FROM dept.Opening with Weak Cursor Types PACKAGE pkg IS TYPE cv_type IS REF CURSOR. END. END. FUNCTION open_emp_or_dept (get_type_in IN VARCHAR2) RETURN pkg. REF TYPE placed in package so that it is "globally" available.page 72 1/21/2011 Copyright 2001 Steven Feuerstein . RETURN retval. PL/SQL Advanced Techniques .cv_type. OPEN retval FOR SELECT * FROM emp. END IF.cv_type IS retval pkg. you can associate any SELECT statement with a weak cursor variable. BEGIN IF get_type_in = µEMP¶ THEN Either query will "do".

 Fetching with cursor variables follows the same rules as those with static cursors.Fetching from the Cursor Variable FETCH cursor_var_name INTO record_name.page 73 . FETCH cursor_var_name INTO var_name. ± The ROWTYPE_MISMATCH exception is raised on failure. it match the cursor type data specification. The INTO structure must match in number and datatype to: ± FOR STRONG cursor types. mismatch. ± FOR WEAK cursor types. it match the OPEN FOR statement structure.   Compatibility checks are performed prior to fetching row.sql 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .. ± Fetching can continue with a different INTO clause. ... var_name.

When to Use Cursor Variables  Make it easier for calling programs (especially non-PL/SQL programs) to manipulate result sets. ± With explicit cursors.sql 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . Use a single block of code to manipulate multiple queries. ± JDBC recognizes cursor variables. ± You could use dynamic SQL to achieve this effect. you have to repeat the code for each cursor.  hccursor.page 74 .  Define a base table block in Forms Builder (formerly Oracle Forms) on stored procedures rather than a table directly. since cursor names are "hard coded". but static cursors are more efficient than dynamic SQL and cursor variables are less complicated than DBMS_SQL.

pkg allcurs. / allcurrs. TYPE cv_t IS REF CURSOR RETURN int_rt. ± It also creates the data structures you will need to call the function. TYPE int_rt IS RECORD (key INTEGER). FUNCTION open (type_in IN INTEGER) RETURN cv_t.tst explcv. bysal CONSTANT INTEGER := 2. END. CREATE OR REPLACE PACKAGE allcurs IS bydept CONSTANT INTEGER := 1.page 75 .Consolidating Different Cursors  The following package specification hides the SQL behind a single open function.sql 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .

Consolidating Different Cursors  The open function simply opens FOR a different SELECT based on the criteria passed to it. / 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . END. END.page 76 . CREATE OR REPLACE PACKAGE BODY allcurs IS FUNCTION open (type_in IN INTEGER) RETURN cv_t IS retval cv_t. RETURN retval. END IF. ELSIF type_in = bysal THEN OPEN retval FOR SELECT empno FROM emp ORDER BY SAL. BEGIN IF type_in = bydept THEN OPEN retval FOR SELECT empno FROM emp ORDER BY deptno.

p.in this case. END. LOOP FETCH cv INTO v_empno. EXIT WHEN cv%NOTFOUND. BEGIN cv := allcurs.l (v_empno).cv_t.open (&1). CLOSE cv.Hiding SQL Variations in Resulting Code  The following block demonstrates that you can alter which SQL statement to query -.page 77 "Report processor" is independent of the particular SELECT . v_empno emp. / 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .empno%TYPE. END LOOP. DECLARE cv allcurs. change the ORDER BY clause -without having to change the code you write.

 Strong and Weak Types ± Create REF CURSORs for specific queries. you can build screens that access data using a cursor variable-based procedural API.page 78 .1.Cursor Variables Let's summarize  Flexibility ± Choose which static SQL statement is executed at run-time. unconstrained type. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .  Hide Variations in Underlying SQL ± You no longer have to repeat the same code for different cursors. or a more general.  Improve Client-Side Access to Data ± At least in Oracle Developer 2.

page 79 .Achieving PL/SQL Excellence Dynamic SQL  Dynamic SQL and dynamic PL/SQL: ± The DBMS_SQL package ± Native dynamic SQL in Oracle8i 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .

What can you do with Dynamic SQL?  Build ad-hoc query and update applications.  Execute dynamically-constructed PL/SQL programs. PL/SQL Advanced Techniques . ± Available in PL/SQL since Release 2.1 and DBMS_SQL.Dynamic SQL and PL/SQL Execution  "Dynamic SQL" mean that you construct the SQL statement or PL/SQL block at runtime and then execute it. you no longer have to write SQL to generate SQL to get your job done. ± One example: implement indirect referencing in PL/SQL.  Execute DDL inside PL/SQL programs.page 80 1/21/2011 Copyright 2001 Steven Feuerstein . ± Very common requirement on the Web. ± Also supported with "native dynamic SQL" in Oracle8i. ± Construct powerful DBA utilities.

page 81 . you can more quickly figure out how to code your solution. If you can recognize the types. These methods are in increasing order of complexity. executed a single time. execute one or more times. Method 3: queries with a fixed number of items in the SELECT list and a fixed number of host variables. ± NDS does not support method 4.Four Methods of Dynamic SQL   Method 1: non-queries without host variables.    1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . ± Different methods require the use of different programs in DBMS_SQL. Method 4: queries with a variable number of items in the SELECT list and/or non-queries with a variable number of host variables. Method 2: non-queries with a fixed number of host variables.

used for multi-row queries. used for DDL. difficult to use. and relatively slow (performance did improve significantly as of Oracle8). 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .Native Dynamic SQL  Prior to Oracle8i.  The new "native dynamic SQL" or NDS of Oracle8i offers two native statements in the PL/SQL language to implement most of your dynamic SQL requirements: ± EXECUTE IMMEDIATE <sql string>.page 82 . ± OPEN FOR <sql string>. you would use the DBMS_SQL built-in package to execute dynamic SQL. ± But this package is very complex. DML and single row fetches.

PL/SQL Advanced Techniques . including objects. define_variables].  Use this statement to execute any dynamic SQL statement (including a PL/SQL block) except for multi-row queries.].page 83   1/21/2011 Copyright 2001 Steven Feuerstein . The USING clause allows you to specify bind arguments or variables to be passed into the SQL string before execution. | record }] [USING {IN | OUT | IN OUT] bind argument [. The INTO clause allows you to pass values from the select list of a single row query into local variables. {IN | OUT | IN OUT] bind argument]...EXECUTE IMMEDIATE EXECUTE IMMEDIATE sql-string [INTO {define_variable[... collections and records.

WHERE clause. '1=1') INTO retval. END IF.sf compare with: tabcount.COUNT(*) For Any Table  Here's a handy and simple utility based on NDS: CREATE OR REPLACE FUNCTION tabCount ( tab IN VARCHAR2.page 84 .000.PUT_LINE ( 'Not the best health care system in the world. 'insured = ''NO''') > 40.' || tab || ' WHERE ' || NVL (whr. USER) || '. sch IN VARCHAR2 := NULL) RETURN INTEGER IS Specify schema. 1/21/2011 Copyright 2001 Steven Feuerstein tabcount81. table and retval INTEGER... BEGIN EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM ' || NVL (sch. RETURN retval.sf PL/SQL Advanced Techniques . IF tabCount ('citizens'.. END. and not much of a democracy either!')..000 THEN DBMS_OUTPUT. whr IN VARCHAR2 := NULL.

1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . start_in IN DATE.page 85 . name_in IN VARCHAR2) IS v_str VARCHAR2 (100). CREATE OR REPLACE PROCEDURE updnumval ( tab_in IN VARCHAR2.'. Pass in bind variables with USING clause. END.. EXCEPTION WHEN OTHERS THEN pl ('Compile Error "' || SQLERRM || '" on: ' || v_str). end_in IN DATE. col_in IN VARCHAR2. END.  Execute a stored procedure.. val_in IN NUMBER) IS BEGIN EXECUTE IMMEDIATE 'UPDATE ' || tab_in || ' SET ' || col_in || ' = :val WHERE hiredate BETWEEN :lodate AND :hidate' USING val_in.. EXECUTE IMMEDIATE v_str..Other Execute Immediate Examples  Perform an update. PROCEDURE runprog (pkg_in IN VARCHAR2. start_in. end_in. END. BEGIN v_str := 'BEGIN ' || pkg_in || '.' || name_in || '.

cond IN preexisting_conditions) IS BEGIN EXECUTE IMMEDIATE 'INSERT INTO ' || tabname (hosp_name) || ' VALUES (:revenue_generator.. END. ± No special syntax needed. pers IN Person. the USING clause allows me to pass an object and nested table to an INSERT statement with a variable table name.Using Objects and Collections in NDS  One of the key advantages to NDS over DBMS_SQL is that it works with Oracle8 datatypes. 1/21/2011 Copyright 2001 Steven Feuerstein health$. :revenue_inhibitors)' USING pers. ± In the following example.pkg PL/SQL Advanced Techniques . cond. including objects and collections.. PROCEDURE add_profit_source ( hosp_name IN VARCHAR2.page 86 .

col IN VARCHAR2. BEGIN OPEN cv FOR 'SELECT ' || col || ' FROM ' || tab || ' WHERE ' || NVL (whr.Multiple Row Queries and NDS  Oracle extends the cursor variable feature of Oracle7 to support multi-row dynamic queries. cv cv_type. '1 = 1'). DBMS_OUTPUT. showcol. CREATE OR REPLACE PROCEDURE showcol ( tab IN VARCHAR2. ndsutil.PUT_LINE (val).pkg 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . CLOSE cv. whr IN VARCHAR2 := NULL) IS TYPE cv_type IS REF CURSOR. val VARCHAR2(32767). LOOP Familiar cursor FETCH cv INTO val. END LOOP.sp END. number or string column in any table. ± Here is a simple utility the displays the values of any date. variable syntax! EXIT WHEN cv%NOTFOUND.page 87 .

) through the USING clause. You cannot pass the NULL literal directly in the USING clause. str2list. You can have duplicate placeholders (for bind arguments). Instead. column names. ± If dynamic PL/SQL. etc. pass a variable with a NULL value. The USING clause for a query can only have IN bind arguments.page 88 .pkg    1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . provide a value for each distinct placeholder (by name). then you provide a value for each placeholder (by position).Some Fine Print for NDS  You cannot pass schema elements (table names. ± If dynamic SQL.

The overhead for using DBMS_SQL has decreased significantly in Oracle8 and again in Oracle8i. Supports all four methods of dynamic SQL. DBMS_SQL is a very large and complex package.Dynamic SQL using DBMS_SQL  Prior to Oracle8i.page 89 . the only way to perform dynamic SQL was with the DBMS_SQL package. with many rules to follow and lots of code to write.     1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . in particular method 4. You should only use DBMS_SQL when you cannot use NDS.

Learning Through Examples  DDL ± Create an index from within PL/SQL  DML ± Update rows in a table  DML with binding ± Update rows using bind variables  Queries ± Method 3 and a dynamic WHERE clause  PL/SQL Version of "SELECT *" ± Example of Method 4  PL/SQL ± Create a generic calculation program 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .page 90 .

± Parse and execute that DDL statement. DBMS_SQL. PL/SQL Advanced Techniques .EXECUTE (cur).page 91 1/21/2011 Copyright 2001 Steven Feuerstein . DDL_statement VARCHAR2(200) := 'CREATE INDEX ' || index_in || ' ON ' || tab_in || ' ( ' || col_in || ')'. fdbk INTEGER. col_in IN VARCHAR2) IS cur INTEGER := DBMS_SQL. ± Construct the DDL statement as a string.DDL with Dynamic SQL PROCEDURE create_index (index_in IN VARCHAR2.PARSE (cur.OPEN_CURSOR. END.sp Creates an index on any column(s) in any table in your schema. BEGIN DBMS_SQL.  creind. DBMS_SQL. fdbk := DBMS_SQL. tab_in IN VARCHAR2.NATIVE).CLOSE_CURSOR (cur). DDL_statement. which will be used to execute the DDL statement. ± Open a cursor.

val_in IN NUMBER) IS cur PLS_INTEGER := DBMS_SQL. 'UPDATE emp SET ' || col_in || ' = ' || val_in || ' WHERE ename LIKE UPPER (''' || ename_in || ''')'.EXECUTE (cur). ename_in IN emp. END.Updates with Dynamic SQL  Update numeric column for specified employees.page 92 . CREATE OR REPLACE PROCEDURE updnumval ( col_in IN VARCHAR2. fdbk := DBMS_SQL.sp 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .ename%TYPE.OPEN_CURSOR. DBMS_SQL.PUT_LINE ('Rows updated: ' || TO_CHAR (fdbk)). updnval1.NATIVE). BEGIN DBMS_SQL. DBMS_OUTPUT.PARSE (cur.CLOSE_CURSOR (cur). DBMS_SQL. fdbk PLS_INTEGER.

DBMS_OUTPUT.sp 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . BEGIN DBMS_SQL. fdbk := DBMS_SQL.EXECUTE (cur). DBMS_SQL.PARSE (cur. END. 'hidate'. end_in). CREATE OR REPLACE PROCEDURE updnumval ( col_in IN VARCHAR2.BIND_VARIABLE (cur.sp updnval3.page 93 .PUT_LINE ('Rows updated: ' || TO_CHAR (fdbk)). updnval2. end_in IN DATE. DBMS_SQL. start_in IN DATE. start_in).NATIVE).BIND_VARIABLE (cur. val_in IN NUMBER) IS cur PLS_INTEGER := DBMS_SQL. 'lodate'. DBMS_SQL. 'UPDATE emp SET ' || col_in || ' = ' || val_in || ' WHERE hiredate BETWEEN :lodate AND :hidate'. DBMS_SQL.Updates with Bind Variables  Update salaries for date range using binding.CLOSE_CURSOR (cur).OPEN_CURSOR. fdbk PLS_INTEGER.

page 94 .Processing Flow for a Dynamic Query Allocate cursor memory (OPEN_CURSOR) Fill cursor with data (EXECUTE) Make sure SELECT is well formed (PARSE) Fill buffer with data (FETCH_ROWS) (EXECUTE_AND_FETCH) Bind any variables (BIND_VARIABLE) (BIND_ARRAY) Retrieve the data (COLUMN_VALUE) Give cursor structure (DEFINE_COLUMN) (DEFINE_ARRAY) Release cursor memory (CLOSE_CURSOR) 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .

END. BEGIN DBMS_SQL. DBMS_OUTPUT. END LOOP. ename FROM emp ' || ' WHERE ' || NVL (where_in.sp showemp2. 1. 1/21/2011 Copyright 2001 Steven Feuerstein showemps.empno).EXECUTE (cur).Queries with Dynamic SQL  Show employees using a dynamic WHERE clause.. 2. DBMS_SQL. '1=1').page 95 .OPEN_CURSOR.COLUMN_VALUE (cur.tst PL/SQL Advanced Techniques .PUT_LINE (TO_CHAR (rec. 1).PARSE (cur. DBMS_SQL.DEFINE_COLUMN (cur.DEFINE_COLUMN (cur.NATIVE). 2. rec.FETCH_ROWS (cur) = 0.empno) || '=' || rec. 'SELECT empno. DBMS_SQL.CLOSE_CURSOR (cur).sp showemps. 60). rec emp%ROWTYPE. fdbk INTEGER. LOOP EXIT WHEN DBMS_SQL.. rec.ename). 'a'. DBMS_SQL.COLUMN_VALUE (cur.ename). DBMS_SQL. CREATE OR REPLACE PROCEDURE showemps (where_in IN VARCHAR2 := NULL) IS cur INTEGER := DBMS_SQL. fdbk := DBMS_SQL. 1. DBMS_SQL.

END. ± The resulting code is much more complicated. END LOOP. FOR each-column-in-table LOOP DBMS_SQL. val). PL/SQL Advanced Techniques . FOR each-column-in-table LOOP DBMS_SQL.COLUMN_VALUE (cur.PARSE (cur.NATIVE).DEFINE_COLUMN (cur. nth_col. END LOOP.Dynamic SELECT * FROM Any Table  Method 4 example: the number of columns queried changes with each table.page 96 Very simplified pseudo-code intab.sp 1/21/2011 Copyright 2001 Steven Feuerstein . DBMS_SQL. LOOP fetch-a-row. END LOOP. nth_col. BEGIN FOR each-column-in-table LOOP add-column-to-select-list. END LOOP. DBMS_SQL. select_string. datatype).

EXECUTE_AND_FETCH (cur).  Makes it easy to execute and fetch a single row from a query. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .page 97 . raises NO_DATA_FOUND or raises the TOO_MANY_ROWS exception. TRUE). which returns a single row. ± Even if the exception is raised. exact_match IN BOOLEAN DEFAULT FALSE) RETURN INTEGER.EXECUTE_AND_FETCH (cur. then EXECUTE_AND_FETCH will raise the TOO_MANY_ROWS exception if more than one row is fetched by the SELECT. the first row will still be fetched and available. ± Very similar to the implicit SELECT cursor in native PL/SQL. ± If exact_match is TRUE. numrows := DBMS_SQL.Using EXECUTE_AND_FETCH FUNCTION execute_and_fetch (cursor_in IN INTEGER. numrows := DBMS_SQL.

FUNCTION dyncalc ( oper_in IN VARCHAR2. I would have to modify my screen every time a new formula was added. NULL. NULL. NULL.Dynamic Formula Execution  Suppose I am building a user interface that allows a user to select a formula for execution. nargs_in IN INTEGER := arg1_in IN VARCHAR2 := arg3_in IN VARCHAR2 := arg5_in IN VARCHAR2 := arg7_in IN VARCHAR2 := arg9_in IN VARCHAR2 := ) RETURN VARCHAR2. arg10_in IN VARCHAR2 := NULL dyncalc.sf dyncalc. a single function will do the trick. arg6_in IN VARCHAR2 := NULL. NULL. arg2_in IN VARCHAR2 := NULL. and enter the arguments. ± With DBMS_SQL. arg4_in IN VARCHAR2 := NULL. 0. ± Using static PL/SQL.page 98 . NULL. arg8_in IN VARCHAR2 := NULL.pkg 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .

END. µsalout¶. my_salary). END. :salout). µdeptin¶.sp dynplsql. µsalout¶. DBMS_SQL. fdbk := DBMS_SQL.  Use BIND_VARIABLE to bind any placeholders in the string -. Use VARIABLE_VALUE to extract a value from any variable you have bound.page 99 .tst    1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .sql dynplsql. DBMS_SQL.More on Dynamic PL/SQL BEGIN cur := open_and_parse ('BEGIN get_max_sal (:deptin.'). Possibilities inherent in dynamic PL/SQL are mind-boggling! dynplsql. DBMS_SQL.EXECUTE (cur). my_salary). v_deptin).VARIABLE_VALUE (cur.BIND_VARIABLE (cur. You must have a BEGIN-END around the code.BIND_VARIABLE (cur.even OUT arguments which are not being bound to any values.

PARSE (v_cur. retval).NATIVE). DBMS_SQL. DBMS_SQL. 'BEGIN :val := ' || nm || '. END.pkg dynvar. DBMS_SQL. fdbk := DBMS_SQL.OPEN_CURSOR. 'val'.EXECUTE (v_cur). PL/SQL does not support indirect referencing. 2000). DBMS_SQL.VARIABLE_VALUE (v_cur. RETURN retval.page 100  dynvar. but you can accomplish much of the same thing with dynamic PL/SQL execution.Indirect Referencing with Dyn PL/SQL  Oracle Forms offers support for indirect referencing with the NAME_IN and COPY built-ins. Here is an example of a "PL/SQL NAME_IN": FUNCTION valbyname (nm IN VARCHAR2) RETURN VARCHAR2 IS v_cur PLS_INTEGER := DBMS_SQL. PL/SQL Advanced Techniques . 'a'. END. retval PLV. 'val'.BIND_VARIABLE (v_cur. BEGIN DBMS_SQL.CLOSE_CURSOR (v_cur). fdbk PLS_INTEGER.tst 1/21/2011 Copyright 2001 Steven Feuerstein .'.dbmaxvc2.

page 101 .  IS_OPEN ± Is the cursor already open?  LAST_ERROR_POSITION ± Returns relative column position in cursor of text causing error condition. ± Call these immediately after your usage to make sure they refer to your cursor.  LAST_ROW_COUNT ± Returns the cumulative count of rows fetched from the cursor.DBMS_SQL Status Built-ins  The package offers a set of modules to return information about the lastoperated cursor in your session.  LAST_SQL_FUNCTION_CODE ± Returns SQL function code of cursor.  LAST_ROW_ID ± Returns the ROWID of last row processed. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .

± DBMS_SQL. dumplong.tst 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .COLUMN_VALUE_LONG   First.page 102 . Then you retrieve the column using the special COLUMN_VALUE_LONG variant. you define the column as a LONG.DEFINE_COLUMN_LONG ± DBMS_SQL.pkg dumplong.Working with LONG Values  DBMS_SQL provides special procedures so that you can extract values from a LONG column in a table. ± Transfer the LONG contents into an index-by table so that you can transfer a value of more than 32K bytes into your PL/SQL program.

New DBMS_SQL Features PL/SQL8 Extensions to DBMS_SQL 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .page 103 .

inserts. ± Support for RETURNING clause to avoid unnecessary queries. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .New Features in DBMS_SQL  The functionality of DBMS_SQL has been extended in Oracle8 in several ways: ± Parse very long SQL strings ± Describe cursor columns ± Use "array processing" to perform bulk updates. deletes and fetches.page 104 .

 Before PL/SQL8.DESCRIBE_COLUMNS (c IN INTEGER.page 105 .  Returns all of the column information in an index table of records. desc_t OUT DBMS_SQL. col_cnt OUT INTEGER. ± Now you can call the DBMS_SQL. it was not possible to determine the datatypes of the columns defined in a cursor.DESCRIBE_COLUMNS.DESC_TAB). 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .Describing Cursor Columns PROCEDURE DBMS_SQL. ± The record TYPE is also defined in DBMS_SQL.

Basic Steps to Describe Columns  The following script shows the individual steps you will need to perform in order to use this feature. END LOOP. empno FROM emp'. DBMS_SQL. BEGIN DBMS_SQL.CLOSE_CURSOR (cur). END. ncols LOOP DBMS_OUTPUT. ncols.DESCRIBE_COLUMNS (cur. DBMS_SQL.pkg desccols.tst showcols.sp 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .col_name). cols DBMS_SQL. FOR colind IN 1 . cols)..NATIVE).OPEN_CURSOR.page 106 .PARSE (cur.PUT_LINE (cols(colind). desccols. ncols PLS_INTEGER. CREATE OR REPLACE PROCEDURE show_columns IS cur PLS_INTEGER := DBMS_SQL.DESC_TAB. DBMS_SQL. 'SELECT hiredate.

It really isn't "array processing". can offer a significant performance boost over Oracle7 dynamic SQL.. deletes and fetches. ± In actuality. DBMS_SQL is executing the specified SQL statement N times. Instead of providing a scalar value for an operation.page 107 .e. where N is the number of rows in the table. index tables. when you perform updates."Array Processing" in DBMS_SQL  PL/SQL8 now allows you to specify the use of "arrays". inserts. however.    This technique still. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . you specify an index table. i. DBMS_SQL then repeats your action for every row in the table.

± With NDS. though you could write variations for those as well. column names.pkg whichsch. and easier code to write. only possible for statements that do not need USING and INTO clauses.sql openprse. ± Otherwise that SQL will be executed under the authority of the owner of the code.  Encapsulate statements to improve error handling. concatenate) whenever possible. effdsql. ± Encapsulate DBMS_SQL. not the invoker of the code.PARSE so that you include the trace in that program. etc.page 108 .) through the USING clause.Recommendations for Dynamic SQL  Bind (vs. ± Increased chance of reusing parsed SQL.sql 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . ± But remember: you cannot pass schema elements (table names.  Use the Oracle8i invoker rights model whenever you want to share your dynamic SQL programs among multiple schemas.

page 109 .NDS or DBMS_SQL: Which is Best?  Dynamic SQL and PL/SQL is very useful. Both implementations will still come in handy. you have upgraded to Oracle8i!  Major Advantages of NDS: ± Ease of use ± Performance ± Works with all SQL datatypes (including userdefined object and collection types) ± Fetch into records  When You'd Use DBMS_SQL: ± ± ± ± ± ± ± Method 4 Dynamic SQL DESCRIBE columns of cursor SQL statements larger than 32K RETURNING into an array Reuse of parsed SQL statements Bulk dynamic SQL Available from client-side PL/SQL 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . but DBMS_SQL is hard to use.. ± If.. of course.

Achieving PL/SQL Excellence Oracle Advanced Queuing  The high performance. asynchronous.page 110 . persistent messaging subsytem of Oracle 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .

page 111 . consistent manner. systems are now heavily reliant on the ability of components to communicate with each other in a dependable. Distribution Center Coffee Beans Producer Shipping Service Retailer Consumer 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .Who Needs Messaging? Everyone!  In the distributed world of the Internet.

Applications Relying on Messaging     Stock trading system Airline reservation system Auction portals Any e-commerce application 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .page 112 .

AQ now offers a publish/subscribe style of messaging between applications. the listen feature and notification capabilities. scalability and reliability all carry over to queues ± Strong history and retention ± Backup and recovery ± Comprehensive journaliing  Rich message content increases usefulness of queueing ± Use object types to define highly structured payloads  New to Oracle8i. message propagation. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . ± Rule-based subscribers.page 113 .Key Features of Oracle AQ  Leverage full power of SQL ± Messages are stored in database tables  Database high availability.

AQ architectural overview Queue Monitor process Queue table Queue ³Producers´ Enqueued messages Message 4 Message 3 Message 2 Message1 ³Consumers´ Dequeued messages Messages include both control information and ³payload´ (content) 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .page 114 .

page 115 1/21/2011 Copyright 2001 Steven Feuerstein .Oracle AQ Highlights  In 8.0. AQ supports: ± ± ± ± ± Multiple queues Resetting order and priority of queued items Queue management using only SQL & PL/SQL Multiple message recipients Propagation of queue to remote servers  Oracle8i adds: ± ± ± ± Rules-based publish & subscribe Listening on multiple queues Easier monitoring Native Java interface PL/SQL Advanced Techniques .

page 116 . Underlying database tables and views The queue monitor (background process) ± Set # of processes with the AQ_TM_PROCESSES initialization parameter.    1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .AQ Components  The DBMS_AQ package offers enqueue and dequeue capabilities The DBMS_AQADM package provides administrative functionality to manage queues and queue tables.

page 117 . storage clause. whether multiple consumers Drops table if all queues in the table have been stopped Associates queue table with queue. optionally waiting for outstanding transactions Adds an ³agent´ as a subscriber 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . assigns retry and retention properties to queue Drops a stopped queue Can also turn on/off enqueue and dequeue operations Stops queue.DBMS_AQADM Highlights CREATE_QUEUE_TABLE DROP_QUEUE_TABLE CREATE_QUEUE DROP_QUEUE START_QUEUE STOP_QUEUE ADD_SUBSCRIBER Assigns name. payload type. sort column.

page 118 . / BEGIN DBMS_AQADM.CREATE_QUEUE (queue_name => 'msgqueue'. 1/21/2011 Copyright 2001 Steven Feuerstein aq.CREATE_QUEUE_TABLE (queue_table => 'msg'. queue_table => 'msg'). END.Creating Queue Tables and Queues CREATE TYPE message_type AS OBJECT (title VARCHAR2(30). Define the "payload" Create the queue table DBMS_AQADM.pkg Start the queue PL/SQL Advanced Techniques . Define a queue in the queue table DBMS_AQADM. queue_payload_type => 'message_type').START_QUEUE (queue_name => 'msgqueue'). text VARCHAR2(2000)).

 ENQUEUE puts a message into a specified queue.sql 1/21/2011 Copyright 2001 Steven Feuerstein .page 119   aq.The "operational package": DBMS_AQ  DBMS_AQ is deceptively simple. but lots of complexity buried inside the parameters of these procedures. and returns a RAW message handle DEQUEUE extracts a message from a specified queue Parameters control message properties such as: ± Visibility (ON_COMMIT or IMMEDIATE) ± ± ± ± Priority Delay Expiration Locking behavior PL/SQL Advanced Techniques . ± Only two procedures.

. DBMS_AQ.Simple Enqueue Example DECLARE queueopts DBMS_AQ. END..ENQUEUE_OPTIONS_T. msgid).'). msgid aq.MESSAGE_PROPERTIES_T. msgprops DBMS_AQ. PL/SQL Advanced Techniques . queueopts. 'May there be many more. msgprops. BEGIN my_msg := message_type ( 'First Enqueue'.page 120 1/21/2011 Copyright 2001 Steven Feuerstein .* Place the message on the specified queue and get a msg ID in return.msgid_type.ENQUEUE ( 'msgqueue'. Set up the payload with an object constructor. Declare records to hold various enqueue and msg properties. aqenq*. my_msg message_type. my_msg.

delay := 3 * 60 * 60 * 24. Same setup as previous page . msgprops. queueopts...... my_msg.. msgid1). my_msg. PL/SQL Advanced Techniques . queueopts.relative_msgid := msgid1.ENQUEUE ('msgqueue'. END.').. msgprops.').ENQUEUE ( 'msgqueue'.sequence_deviation := DBMS_AQ. DBMS_AQ.BEFORE. queueopts. Modify the dequeue sequence by changing the deviation field and relative msg ID. msgid2). BEGIN my_msg := message_type ( 'First Enqueue'. 'And this one goes first.. my_msg := message_type ( 'Second Enqueue'. 'May there be many more. 1/21/2011 Copyright 2001 Steven Feuerstein Specify a delay before the payload is available.page 121 .More Interesting Enqueue Example DECLARE . DBMS_AQ. queueopts. msgprops.

msgid aq.DEQUEUE_OPTIONS_T.REMOVE). msgid). END. /* defined in aq. queueopts.Dequeue Example DECLARE queueopts DBMS_AQ. END. msgprops. Dequeue operation isolated in local module. getmsg (DBMS_AQ.BROWSE).REMOVE). msgprops DBMS_AQ.MESSAGE_PROPERTIES_T.dequeue_mode := mode_in.msgid_type. my_msg. getmsg (DBMS_AQ. BEGIN getmsg (DBMS_AQ. DBMS_AQ. Demonstrates destructive and non-destructive dequeuing. aqdeq*.* Declare records to hold various dequeue and msg properties.DEQUEUE ( 'msgqueue'. PL/SQL Advanced Techniques .page 122 1/21/2011 Copyright 2001 Steven Feuerstein .pkg */ my_msg message_type. PROCEDURE getmsg (mode_in IN INTEGER) IS BEGIN queueopts.

ENQUEUE_OPTIONS_T. queueopts. DBMS_AQ. g_priority := g_priority . BEGIN item_obj := aqstk_objtype (item). msgid). item_obj. ± The lower the numeric priority value. PROCEDURE push (item IN VARCHAR2) IS queueopts DBMS_AQ.Prioritized Payloads  You can assign priorities to individual payloads and then dequeue according to those priorities. msgprops.ENQUEUE ( c_queue.page 123 .pkg aqstk2.1. msgprops DBMS_AQ. msgprops.visibility := DBMS_AQ. queueopts. item_obj aqstk_objtype.msgid_type. the higher the priority.pkg priority. msgid aq.MESSAGE_PROPERTIES_T.  A stack implementation using AQ demonstrates this well.IMMEDIATE. END. aqstk.priority := g_priority.* 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .

BEGIN DBMS_AQADM. NULL. Add subscribers for the queue. DBMS_AQADM. The queue table must be defined to support multiple subscribers or consumers. SYS.page 124 .Defining Message Subscribers  You can specify that a message is to be enqueued for a list of subscribers. ± 2. multiple_consumers => TRUE).ADD_SUBSCRIBER ( c_queue.AQ$_AGENT (name_in. queue_payload_type => 'student_major_t'. NULL)).* PL/SQL Advanced Techniques . 1/21/2011 Copyright 2001 Steven Feuerstein aqmult*. ± The message is then not removed from the queue until all subscribers have dequeued the message.  Steps to working with a subscriber list: ± 1.CREATE_QUEUE_TABLE ( queue_table => 'major_qtable'.

page 125 . ± Significant enhancements in Oracle8i. ± Crucial for Oracle to have a message-oriented middleware in order to offer an all-Oracle solution.Oracle AQ .Summary  Very powerful and flexible architecture. supporting a publish-subscribe model. ± Should be strongly supported "down the road". LISTEN capability. improved security.  Considered by Oracle to be a core component of its overall solution. ± Much more robust that DBMS_PIPE. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .

Achieving PL/SQL Excellence Managing Large Objects with DBMS_LOB 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .page 126 .

± Oracle has announced deprecation of LONGs. video. they should no longer be used. Images.  1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .LOB Terms  LOB = Large OBject: a category of datatype allowing storage of ³unstructured´ data up to 4 gigabytes LOB datatype can be: ± Column in table ± Attribute in object type ± Element in nested table   Possible applications include office documents. LOB datatypes are the successor to LONGs. etc. though they will probably not be actually desupported.page 127 . sounds.

external do not ± External LOBs are read-only from within Oracle 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .  Key programming differences: ± Internal LOBs participate in transactions. improving performance.Types of Large Objects  ³Internal´ LOBs ± BLOB: unstructured binary data ± CLOB: single-byte fixedwidth character data ± NCLOB: multi-byte fixedwidth character data (or varying width in )  ³External´ LOBs ± BFILE: pointer to an operating system file  Temporary LOBs ± Internal LOBs that do not participate in transactions.page 128 .

substring and instring searches. open. copy. comparison and length checking ± For internal LOBs: Write.PL/SQL built-ins for LOBs  Package DBMS_LOB ± Supports for all LOBs: Reading. trim ± For external LOBs: File existence test.page 129 . append. erase. EMPTY_CLOB() ± BFILENAME 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . close  Other built-in functions ± LOADFROMFILE (load an external BFILE into a BLOB) ± EMPTY_LOB().

FETCH fax_cur INTO the_fax. CLOSE fax_cur.page 130 .  Retrieve record with BLOB into PL/SQL variable DECLARE CURSOR fax_cur IS SELECT fax FROM incoming_faxes. END. BEGIN OPEN fax_cur. fax BLOB). Question: What¶s in the_fax? 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . the_fax BLOB.Deceptively simple example  BLOB-typed column in a table CREATE TABLE incoming_faxes (fax_id INTEGER. received DATE.

tt LOBs <lob segment> fax_id 281937 received 12-JAN-98 fax <lob locator> Updati  t e LOB anges t e pointer is ompli ates se of LOBs ± LOB locators cannot span transactions ± Programs must lock records containing LOBs efore updating ± Programs performing L must accommodate dynamic LOB locator alues 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .The ³LOB locator´ LOB t l sel es [ ll ] t i i t r .page 131 .

oodb. ...Example: Piecewise CLOB programmatic insert  Create a table CREATE TABLE web_pages ( url VARCHAR2(512) PRIMARY KEY. htmlloc CLOB).page 132 . 1 of 2  Must get a new LOB locator before writing into the LOB: DECLARE the_url web_pages. EMPTY_CLOB()) RETURNING htmlloc INTO the_loc. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . the_loc CLOB. BEGIN INSERT INTO web_pages VALUES (the_url.com'.url%TYPE := 'http://www.

the_loc CLOB.WRITE(lob_loc => the_loc. DBMS_LOB.HTML_PIECES. Note: We are ignoring amount => piece_length.com'.page 133 1/21/2011 Copyright 2001 Steven Feuerstein BEGIN .oodb. buffer => html_tab(the_piece_no)). piece_length PLS_INTEGER. FOR the_piece_no IN 1. END LOOP. This block retrieves INSERT INTO web_pages VALUES (the_url.REQUEST_PIECES(url => the_url). running_total PLS_INTEGER := 1. html_tab UTL_HTTP. END.html_tab.. EMPTY_CLOB()) and loads a web page RETURNING htmlloc INTO the_loc.url%TYPE := 'http://www. several likely exceptions offset => running_total. running_total := running_total + piece_length.COUNT LOOP piece_length := LENGTH(html_tab(the_piece_no)). PL/SQL Advanced Techniques .Example: Piecewise CLOB programmatic insert DECLARE the_url web_pages. into a CLOB column html_tab := UTL_HTTP.

INSTR(lob_loc => the_loc.oodb. buffer => 'cool').Example: Piecewise CLOB programmatic update DECLARE Program must lock the record explicitly CURSOR hcur IS SELECT htmlloc FROM web_pages WHERE url = 'http://www. END IF.WRITE(lob_loc => the_loc.page 134 . FETCH hcur INTO the_loc. IF str_offset != 0 THEN DBMS_LOB. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . offset => str_offset.com' FOR UPDATE. CLOSE hcur. END. str_offset := DBMS_LOB. amount => 4. str_offset INTEGER. pattern => 'oodb'). the_loc CLOB. BEGIN OPEN hcur.

1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .  Example: CREATE DIRECTORY web_pix AS 'D:\bill\training\pix'.page 135 .Preparing to use BFILEs  You must first create an Oracle I ORY´ ± Creates logical alias for full directory pat ± imilar to LIBRARY (used for C "external procedures"). ut IRECTORY namespace is global  Syntax: CREATE OR REPLACE DIRECTORY <directory name> AS '<full path to directory>'.

page 136 .. CREATE TYPE Business_card_t AS OBJECT ( name Name_t. / 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . phones Phone_tab_t.  In an object type. scanned_card_image BFILE ). image BFILE).... CREATE TABLE web_graphics ( image_id INTEGER.Using BFILE datatype in DDL  In a table. addresses Address_tab_t.

file_exprn) RETURN BFILE.gif'). Spec: FUNCTION BFILENAME(directory_exprn. 'prodicon. END. BEGIN INSERT INTO web_graphics VALUES (100015.page 137 .The built-in BFILENAME function  Returns value of datatype BFILE. picture).  Example: DECLARE picture BFILE := BFILENAME('WEB_PIX'. /  Notes: ± No automatic file checking or synchronization ± No participation in transactions 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .

DBMS_LOB. amount => DBMS_LOB.LOADFROMFILE(dest_lob => pic_blob_loc.gif'). DBMS_LOB. pic_blob_loc BLOB := EMPTY_BLOB(). END.FILE_READONLY).Loading File into Database BLOB CREATE TABLE web_graphic_blobs ( image_id INTEGER. pic_blob_loc) RETURNING image INTO pic_blob_loc. src_lob => pic_file.FILEOPEN(pic_file. / loadblob. DBMS_LOB. BEGIN INSERT INTO web_graphic_blobs VALUES (1. DBMS_LOB.page 138 . 'prodicon.sql 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . image BLOB).GETLENGTH(pic_file)). DECLARE pic_file BFILE := BFILENAME('WEB_PIX'.FILECLOSE(pic_file).

that can mean less I/O » Trigger will not fire until CLOSE » Indexes will not update until CLOSE ± ISOPEN 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . call.page 139 . or transaction  Ability to retrieve LOB ³chunk size´ ± Allows programmer to tune READs and WRITEs  For all internal LOBs ± OPEN & CLOSE allow control over timing.New DBMS_LOB APIs in 8i  Support for temporary LOBs ± No logging or rollback faster! ± Lifespan: session.

. ± Complete support in PL/SQL (and other APIs) ± Much better performance and control than with LONGs ± Usable in object types HOT  Some weaknesses.Summary  LOB support in Oracle is now significantly improved. ± LOB locator behavior slightly abstruse ± Inability to modify BFILEs directly from within PL/SQL.page 140 . COLD 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .Large Object ..

page 141 .Achieving PL/SQL Excellence Leveraging Java Inside PL/SQL 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .

Overview of Java interoperability  Java inside or outside 8i server can call PL/SQL ± Standard JDBC and SQLJ calls with Oracle extensions ± Same Java on client. PL/SQL Advanced Techniques . or server Not covered in this seminar  PL/SQL can call Java inside 8i server ± ± ± ± Command-line tools load Java classes DDL extensions publish Java classes Writing stored procedures. mid-tier.. functions.. triggers in Java Distinct Java & PL/SQL namespaces  But first.page 142 1/21/2011 Copyright 2001 Steven Feuerstein ..a BRIEF introduction to Java..

± The end of programming history as we know it? ± The easiest.Question 1: What is Java?  Could it be. ± We just need to keep a firm grip on common sense and stay focused on delivering solutions..page 143 . fastest. slickest piece of software ever designed by human beings? ± Just the latest in a series of "silver bullets" promoted by software vendors in order to prop up quarterly sales? ± The first and only successful O-O language? ± None of the above?  We don't really need to take a vote.. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .

± Ubiquitous in thousands of production applications and millions of lines of code.  1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . it is very unlikely and totally unthinkable for years to come. ± A language in which hundreds of thousands of developers are trained.and very aggressively.Question 2: Will Java Replace PL/SQL?  While that scenario is certainly possible. PL/SQL will still be: ± Faster and more productive than Java for database operations. ± Supported and improved by Oracle -. to boot.page 144 .

page 145 . ± Well.  You don't have to know how to do everything with Java to get lots of value out of it. everything exception the primitive datatypes. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .Some Important Things to Remember  Java is a case sensitive language. you have to instantiate an object from that class.. ± Don't get overwhelmed by all the classes and all the strange quirks.... ± string is definitely not the same as String..  Everything is a class (or an object instantiated from a class).. ± Before you can call a (non-static) class method.

± Used to test or run stand-alone a class.page 146 . CREATE OR REPLACE PROCEDURE hello IS BEGIN DBMS_OUTPUT. by the way: the PL/SQL version 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .PUT_LINE ('Hello world!'). } }  No members. no methods..Building a Java Class  Let's start from the very beginning.out. END. except the "special" main method. Oh.println ("Hello world!").. public class Hello { public static void main (String[] args) { System.

± This will convert the . e:\jdk1.class file.1.Compiling Classes  Before you can use a class.7b\lib\classes. you must compile it with the javac command. ± It will also automatically recompile any classes used by your class that has not been compiled since last change. ± You must also either have set the CLASSPATH or include it in your javac call.page 147 . SET CLASSPATH = d:\Oracle\Ora81\jdbc\lib\classes111.java file to a .d:\java D:> javac Hello.java -classpath d:\java 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .zip.zip.

Running a Class  Run a class? What does that mean? It means that if your class contains a method with this header: public static void main (String[] args)  then you can "run" the main method with the java command: d:\java> java Hello  You can also pass one or more arguments on the command line: d:\java> java Hello mom Hello2.page 148 .java 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .

  1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .page 149 . you will use a class by instantiating objects from the class and then invoking class methods on the object.Using a Class  The main method is handy for providing a built-in test mechanism of your class. Usually. however. Let's build a performance analyzer class to explore these ideas.

java InFile. class Tmr { private long Gstart = 0. } public void showElapsed (String context) { p. System. } } p.java 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .l ("Elapsed time for " + context.java Tmr.Gstart).l ("Elapsed time ".currentTimeMillis to calculate elapsed time to nearest thousandth of a second.Gstart).page 150 . elapsed()).currentTimeMillis() .Compare Performance of Methods  Use System. public void capture () { Gstart = System. } public long elapsed () { return (System. } public void showElapsed () { p.currentTimeMillis().currentTimeMillis() .

. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .  Inner class ± Classes that are defined inside other classes.Types of Classes  There are several different kinds of classes in Java.page 151 . but at least one method remains unimplemented..  Abstract class ± The class can contain members and methods. besides the "regular" kind we just saw.  Interface class ± The class only contains unimplemented methods.

java A Class Hierarchy Management NonManagement Corporation 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . ± Dynamic polymorphism: form is determined at run-time.And Now for Some Scary Buzzwords!  Inheritance ± Subclasses inherit methods and variables from extended superclasses.  Polymorphism ± An object of a class can have "multiple" forms. either as its own class or as any superclass. supertype/"wider" Citizen Person Employee Hourly Worker Salaried Worker subtype/"narrower" War Criminal Person.page 152 . ± Static polymorphism: form is chosen at compile-time (PL/SQL overloading).

page 153 . boolean char byte short int long float double  Strings ± A String object is a read-only. if you assign a new value to it.Language Basics  Comments // Single line comment /* Block comment */ /** Documentation comment */  Primitive datatypes ± So I lied. String myName. myName = "Feuerstein". you are actually allocating a new object. ± Can't do a direct == comparison. if (myName. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . these are not objects instantiated from classes. myName = "Steven".equals(YourName)) foundFamily().

out. Examples: for (indx indx=0.NextElement()). do-while and for ± Note: you need squiggly brackets only if there is more than one statement in the loop body. for (initialize. step) { lotsaStuff } while (expression) { lostsaStuff } do { lostsaStuff } while (expression). indx++) System.out. indx < args. expression.Writing Loops in Java  Three kinds of loops: while.nextElement()) } } 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .println ( (String)enum.hasMoreElements ()) { processIt (enum. System.length. static void processAll (Enumeration enum) { while (enum.println (args[indx]).page 154 .

page 155 .name()). ± Only positional notation is supported.. public PuterLingo (String name) { mname = name. you must supply a value for each parameter.Passing Parameters  Some important differences from PL/SQL. System. class PuterLingo { private String mname.. } } 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . you still include the open and close parentheses.out. } } class LotsALingos { public static void main (String args[]) { PuterLingo Java = new PuterLingo("Java"). } public String name () { return mname. ± If a method has no arguments.println (Java. ± No default values for arguments.

toString()). you "throw" and "catch" exceptions. } catch (Exception e) { System. "WHEN OTHERS" } in Java } 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . rather than raise and handle.length().println (e. Put inside try clause File myFile = new File (filename).equals("")) throw new Exception ("Filename is NULL").Exception Handling in Java  Very similar to PL/SQL. Throwing my own public static int numBytes (String filename) { exception try { if (filename. } File-related catch (SecurityException e) { exceptions return -1.out. return myFile.page 156 .

± Use the throws clause in your specification. NoSuchFile { . ± So you can pass them as arguments and do anything and everything else you can do with objects.. } 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . as in: public static int numBytes (String filename) throws SecurityException.  You must inform users of your method of which exceptions may be thrown.Differences Between Java & PL/SQL  Exceptions are objects derived directly or indirectly from the Exception class..page 157 .

± Object oriented development (Java) is very different from procedural coding (PL/SQL).page 158 .  Now let's explore how you can put Java to work for you inside PL/SQL programs.Java's Not So Tough!  You can learn enough Java in less than a week to: ± Build simple classes ± Leverage Java inside PL/SQL  Moving to the next level of expertise will be more of a challenge. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .

using JDBC or SQLJ Oracle 8i server PL/SQL cover for Java method Java virtual machine running Java method Oracle Developer client (PL/SQL) Net8 OCI or Pro*C client VB or C++ via OO4O or ODBC 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .Java Stored Procedures (JSPs) Java applet or app.page 159 .

network communication in/out PL/SQL replacement ± More standard language ± Good performer for numeric processing tasks ± Beware database I/O & string manipulation performance Scaleable deployment of third party code ± Vertical application ± Web server ± XML parser/generator 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . better file I/O ± RMI callouts.JSPs: Some sample uses PL/SQL extender ± For example.page 160 .

.page 161 . Call from PL/SQL (or SQL) as if calling PL/SQL    1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques ..Creating JSP to call from PL/SQL   1. Grant privileges as desired 5. Load into server using ³loadjava´ command-line tool 3.. Publish PL/SQL cover using AS LANGUAGE JAVA. rather than BEGIN..END 4. Create Java classes in your favorite IDE 2.

page 162 PL/SQL .println main method is used to test the class. paying its" + " Chief Executive Officer " + CEOCompensation.java Advanced Techniques . long CEOCompensation. long PceoComp) { name = Pname. }} 1/21/2011 Copyright 2001 Steven Feuerstein Notes on Java classes  toString method automatically used by System. layoffs = Playoffs.Create Java class(es) class Corporation extends Person { long layoffs.println (TheGlobalMonster).out. 50000000). } public String toString () { return name + " is a transnational entity with " + layoffs + " laid-off employees. Entry points must be public static in most cases Classes may call other classes Avoid GUI calls     person. 5000000.out. public Corporation ( String Pname. } public static void main (String[] args) { // A very scary company Corporation TheGlobalMonster = new Corporation ( "Northrup-Ford-Mattel-Yahoo-ATT". System. long Playoffs. CEOCompensation = PceoComp.

page 163 .jar file Oracle 8i server Java class Java source Java resource loadjava Example: loadjava loadjava -user scott/tiger -oci8 -resolve datacraft/bill/Hello.java file Java resource file .Upload using ³loadjava´ utility .class file .class options (abbreviated) -oci8 -resolve loadjava will connect using OCI driver Resolves external class references at compile time -resolver (shown later) Search path like CLASSPATH 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .

.bill. /  Syntax (simplified) CREATE [ OR REPLACE PROCE URE FUNCTION <name> <sqlt pe> ] [ [ <ar s> ) ] [ AUTHID { DEFINER | CURRENT_USER } ] AS LANGUAGE JAVA NAME '<met fullname> (<Ja a t pe fullname>.Hello.Publish  Example (top-level call spec) CREATE OR REPLACE FUNCTION hello_emp (empno_in IN NUMBER) RETURN VARCHAR2 AS LANGUAGE JAVA NAME 'datacraft. ..lang.) [ return <Ja a t pe fullname> ]'.page 164 .Emp(int) return java.String'. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .

sql 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .  Method 2: Use 8i SQL CALL statement. END.PUT_LINE(hello_emp(7499)). for example. from SQL*Plus: VARIABLE thename VARCHAR2(12) CALL hello_emp(7499) INTO :thename.page 165 .Call the wrapped method  Method 1: Call as if PL/SQL module BEGIN DBMS_OUTPUT. PRINT :thename ± CALL avoids overhead of SELECT fn FROM DUAL jsp.

STRUCT <named type> oracle.BigDecimal oracle.sql.String java.lang.sql.REF oracle.more concepts Shape mapping ± Java methods declared ³void´ become PL/SQL procedures ± Signature mismatches detected only at runtime Type mapping (typical) VARCHAR2 DATE NUMBER user-defined object type user-defined object type object REFerence user-defined collection type java.sql.math.sql.Publishing -.Timestamp java.page 166 .ARRAY 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .

Emp(int) return java.page 167 .util.Publish in PL/SQL Package Spec  Designate Java module in PL/SQL package spec..Hello. CREATE OR REPLACE PACKAGE hello_pkg AS FUNCTION hi_emp (empno_in IN NUMBER) RETURN VARCHAR2 AS LANGUAGE JAVA NAME 'datacraft.. / (No package body required in this case) 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . END.String'.lang.

Hello.or in package body CREATE OR REPLACE PACKAGE hello_pkg2 AS FUNCTION hi_emp (empno_in IN NUMBER) RETURN VARCHAR2.page 168 .lang.String'..Publish as module in package body  . END.Emp(int) return java.util. / CREATE OR REPLACE PACKAGE BODY hello_pkg2 AS FUNCTION hi_emp (empno_in IN NUMBER) RETURN VARCHAR2 IS LANGUAGE JAVA NAME 'datacraft. / 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . END..

/ 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .page 169 . END.lang. MEMBER FUNCTION hello_emp RETURN VARCHAR2).String').String'. MEMBER FUNCTION hello_emp RETURN VARCHAR2 IS LANGUAGE JAVA NAME 'datacraft.util.lang.Hello.util.Hello. / CREATE OR REPLACE TYPE BODY foo_t AS MEMBER FUNCTION hello_emp RETURN VARCHAR2 IS LANGUAGE JAVA NAME 'datacraft.Publish as object type method  Either in spec: CREATE OR REPLACE TYPE foo_t AS OBJECT ( bar VARCHAR2(30).Emp(int) return java.Emp(int) return java. / or in the body: CREATE OR REPLACE TYPE foo_t AS OBJECT ( bar VARCHAR2(30).

JAVADEBUGPRIV ± You can also grant specific privileges.New DDL Statements and Roles  CREATE JAVA ± Alternative to ³loadjava´ utility ± Creates or replaces an Oracle ³library unit´ from Java source. resolves Java class references. class. DROP JAVA: drops a named Java library unit Several roles available for Java operations: ± JAVAUSERPRIV. or resource ± Can read file designated with BFILE() function  ALTER JAVA: compiles Java source. JAVASYSPRIV (needed for file IO operations).page 170 . JAVAIDPRIV.   1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . JAVA_ADMIN.

sql.CustomDatum ± oracle.page 171 .Passing Oracle8 objects Oracle8i server Object in O-R table Java application Java object   Harder than you¶d think Three different interfacing techniques ± oracle.SQLData 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .sql.jdbc2.STRUCT ± oracle.

JPublisher utility Database server Definition of type or REF in data dictionary User-supplied JPublisher input file What does it do? ± Generates Java that encapsulates type and REF types of mapping supported for methods JPublisher ± ³Oracle mapping´ ± ³JDBC mapping´ ± ³Object JDBC mapping´ Three Generated Java file(s) for use in Java programs 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .page 172 .

bill.sql 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .Account_t)'.AccountRuntime. /  jspobj. they become available to use in mapping Example of passing an Account_t object: CREATE OR REPLACE PROCEDURE account_save (new_acct IN Account_t) IS LANGUAGE JAVA NAME 'datacraft.bill.page 173 .save (datacraft.Passing object using JPub-generated Java  After generating and uploading classes with JPub.

Let's see how we can make that great Java stuff available from within PL/SQL.   1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . Java offers many file-related classes with much greater capabilities. but that package is very limited.Example: Improving File I/O  You can read/write files in PL/SQL with UTL_FILE.page 174 .

Encapsulate Java Classes  You won't generally access native Java methods in your PL/SQL wrapper.page 175 .. ± The File class offers a length method that returns the number of bytes in a file. ± Instead build a static method that instantiates a Java object from the class and then invokes the relevant method against that object.  Let's start with something simple.. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . ± This is not available through UTL_FILE (though you can get it through DBMS_LOB).

My Own Java Class for File Manipulation  Accept the name of a file and return its length. return myFile. ± Instantiate a File object for the specified name.length().io. } } JFile2. import java.java  Take each of these steps: ± Import the File class to resolve reference.File. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . ± Call the method of choice against that object and return the value. public class JFile2 { public static long length (String fileName) { File myFile = new File (fileName).page 176 .

String) return long'.page 177 . CREATE OR REPLACE PACKAGE xfile IS FUNCTION length (file IN VARCHAR2) RETURN NUMBER. / CREATE OR REPLACE PACKAGE BODY xfile IS FUNCTION length (file IN VARCHAR2) RETURN NUMBER AS LANGUAGE JAVA NAME 'JFile. END.pkg 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . ± I translate the Java long to a PL/SQL NUMBER. we will certainly want to add more functionality over time.Build a Package over Java Method  Let's put it in a package. END.length (java.lang. / xfile2.

page 178 . so you'd expect smooth sailing. Write a "hidden" PL/SQL wrapper function that returns the string or number. Convert the Java boolean to a String or number and return that value.Mapping the Boolean Datatype  Both Java and PL/SQL support a native Boolean datatype. Not so! To pass a Boolean back from Java to PL/SQL. you will need to take these steps: ± 1. ± 3. ± 2.  1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . Write a "public" PL/SQL wrapper function to convert that number to a true PL/SQL Boolean.

import java. } } JFile3. public class JFile3 { public static int canRead (String fileName) { File myFile = new File (fileName). 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . ± And don't forget: this is a boolean primitive. else return 0.File.Translate Boolean to Number  Accept the name of a file and return its length. if (retval) return 1.canRead().java  Translate TRUE to 1 and FALSE to 0. boolean retval = myFile. not a Boolean class.io.page 179 .

page 180 .canRead (java. / CREATE OR REPLACE PACKAGE BODY xfile IS FUNCTION IcanRead (file IN VARCHAR2) RETURN NUMBER AS LANGUAGE JAVA NAME 'JFile3.Wrapper for Pseudo-Boolean function  Simple translation back to PL/SQL Boolean. END.String) return int'. xfile4. JFile4. JFile. FUNCTION canRead (file IN VARCHAR2) RETURN BOOLEAN AS BEGIN xfile3..pkg 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .java END.lang.pkg RETURN IcanRead (file) = 1.. ± Avoid the hard-codings with named constants.pkg END.java / xfile. CREATE OR REPLACE PACKAGE xfile IS FUNCTION canRead (file IN VARCHAR2) RETURN BOOLEAN.

java passobj. public class UnionBuster { Obtain attributes of public static void wageStrategy (STRUCT e) the Oracle object. throws java. // Access individual attributes by array index.page 181 . 1/21/2011 Copyright 2001 Steven Feuerstein UnionBuster. } } Extract individual attribute values from the array.tst PL/SQL Advanced Techniques . Object[] attribs = e.getAttributes(). System.out.sql. // starting with 0 String laborType = (String)(attribs[0]). BigDecimal hourly_rate = (BigDecimal)(attribs[1]).Passing Objects to Java with STRUCT  You can pass Oracle object information to Java without relying on JPub by using the STRUCT class.println ( "Pay " + laborType + " $" + hourly_rate + " per hour").SQLException { // Get the attributes of the labor_source object.

sql. '5')). END. 0)).STRUCT)'.Wrapping a STRUCT-based Method  You can pass Oracle object information to Java without relying on JPub by using the STRUCT class.page 182 . 1/21/2011 Copyright 2001 Steven Feuerstein Fully specify the STRUCT class in parameter list. / CREATE OR REPLACE PROCEDURE bust_em_with ( labor_source_in IN labor_source_t) AS LANGUAGE JAVA NAME 'UnionBuster. PL/SQL Advanced Techniques . / BEGIN bust_em_with ( labor_source ('Workfare'. hourly_rate NUMBER). bust_em_with ( labor_source ('Prisoners'. The Oracle object type definition CREATE TYPE labor_source_t AS OBJECT ( labor_type VARCHAR2(30).wageStrategy (oracle.

Viewing Output from Java Methods  Java provides a "print line" method similar to DBMS_OUTPUT.page 183 .println ( "Hello Hello Hello Hello Hello All!").out. HelloAll.tst 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . ± Here is a good nucleus for a login. public class HelloAll { public static void lotsaText ( int count) { for (int i = 0. ± Call it within methods and output will display in your Java environment.sql file: SET SERVEROUTPUT ON SIZE 1000000 CALL DBMS_JAVA.out.println.java HelloAll. you can redirect the output to the DBMS_OUTPUT buffer. i < count. }}}  When called within a PL/SQL wrapper.SET_OUTPUT (1000000).PUT_LINE: System. i++) { System.

± Exceptions are objects instantiated from the Exception class or a subclass of it.  Any error not caught by the JVM (Java virtual machine) will be thrown back to the PL/SQL block or SQL statement. ± Use two methods. such as java.page 184 . ± And also spew out the entire Java error stack! (at least through 8.5).1. ± Instead of raising and handling.SQLException. but more robust error handling mechanism than PL/SQL.sql. you "throw" and "catch".Error Handling with Java-PL/SQL  Java offers a very similar. getErrorCode() and getMessage() to obtain information about the error thrown. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .

OracleStatement.SQLException: getErrInfo. EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT. 'blip').OracleStatement.kprb.jdbc.java) at oracle. / SQL> 2 3 4 5 6 7 8 9 java.sql.java) at oracle.tst ORA-29532: Java call terminated by uncaught Java exception: java.parseExecuteFetch(KprbDBAccess.executeUpdate(OracleStatement. the entire Java stack is displayed on your screen. BEGIN dropany ('TABLE'. END.java:14) DropAny.jdbc.driver.PUT_LINE (SQLCODE).sp dropany2.jdbc.jdbc.java) at oracle.check_error(KprbDBAccess.SQLException: ORA-00942: table or view does not exist at oracle.object(DropAny.tst ORA-00942: table or view does not exist 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .OracleStatement.driver.KprbDBAccess.Trapping and Identifying Errors  Currently.java -29532 dropany.java) at oracle.jdbc.OracleStatement.java) at DropAny.driver.doExecuteOther(OracleStatement.doExecute(OracleStatement.java) at oracle.doExecuteWithTimeout(OracleStatement.PUT_LINE (SQLERRM). DBMS_OUTPUT.java) at oracle.sql.kprb.jdbc.driver.KprbDBAccess.driver.OracleStatement.doExecuteWithBatch(OracleStatement. and you have to do some digging to extract the Oracle error information.jdbc.page 185 .

Achieving PL/SQL Excellence External Procedures  An external procedure is a 3GL routine that can serve as the ³body´ of a PL/SQL function. or method.  An Oracle8 feature that allowed relatively "native" callouts to C from PL/SQL for the first time. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . ± Must be a shared object library on Unix or a dynamically linked library (DLL) on Windows.page 186 . procedure.

page 187 .so file extproc returns results returns results 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .Process & data flow Application Makes request Net8 External Procedure Listener spawns External Shared Library Calls PL/SQL Runtime Engine PL/SQL body Client or server-side application returns results calls routine from Routine in .DLL or .

sql 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .sql diskspace.page 188 .External procedures: Sample uses      Send email Invoke operating system command Invoke custom or legacy application Call C runtime library function Perform admin tasks email.

/ 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .Determine free disk space on NT (1/4)  Use pre-existing routine: ± GetDiskFreeSpaceA in kernel32.dll ± For given drive letter.dll'. this function returns: » » » » » sectors per cluster bytes per sector number of free clusters total number of clusters ³return code´ indicating success or failure  First.page 189 . create an Oracle8 ³library´: CREATE OR REPLACE LIBRARY nt_kernel AS 'c:\winnt\system32\kernel32.

/ 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . bytes_per_sector OUT PLS_INTEGER. total_number_of_clusters OUT PLS_INTEGER) RETURN PLS_INTEGER. number_of_free_clusters OUT PLS_INTEGER. END disk_util.page 190 .Package spec (2/4)  Nothing unexpected here: CREATE OR REPLACE PACKAGE disk_util AS FUNCTION get_disk_free_space (root_path IN VARCHAR2. sectors_per_cluster OUT PLS_INTEGER.

RETURN LONG). PL/SQL Advanced Techniques . END disk_util. total_number_of_clusters OUT PLS_INTEGER) RETURN PLS_INTEGER IS EXTERNAL LIBRARY nt_kernel NAME "GetDiskFreeSpaceA" LANGUAGE C CALLING STANDARD PASCAL PARAMETERS (root_path STRING.Package body in Oracle 8. number_of_free_clusters BY REFERENCE LONG. total_number_of_clusters BY REFERENCE LONG.0 (3/4) CREATE OR REPLACE PACKAGE BODY disk_util AS FUNCTION get_disk_free_space (root_path IN VARCHAR2. bytes_per_sector BY REFERENCE LONG. bytes_per_sector OUT PLS_INTEGER. sectors_per_cluster BY REFERENCE LONG.page 191  All the magic is in the EXTERNAL section 1/21/2011 Copyright 2001 Steven Feuerstein . number_of_free_clusters OUT pls_integer. sectors_per_cluster OUT PLS_INTEGER.

Usage (4/4)
DECLARE lroot_path VARCHAR2(3) := 'C:\'; lsectors_per_cluster PLS_INTEGER; lbytes_per_sector PLS_INTEGER; lnumber_of_free_clusters PLS_INTEGER; ltotal_number_of_clusters PLS_INTEGER; return_code PLS_INTEGER; free_meg REAL; BEGIN return_code := disk_util.get_disk_free_space (lroot_path, lsectors_per_cluster, lbytes_per_sector, lnumber_of_free_clusters, ltotal_number_of_clusters); free_meg := lsectors_per_cluster * lbytes_per_sector * lnumber_of_free_clusters / 1024 / 1024; DBMS_OUTPUT.PUT_LINE('free disk space, Mb = ' || free_meg); diskspace.sql END;
1/21/2011 Copyright 2001 Steven Feuerstein
PL/SQL Advanced Techniques - page 192

Creating your own external procedure 

1. Identify or create shared library 2. Identify or CREATE LIBRARY within Oracle 3. Map the parameters using:
± EXTERNAL clause (Oracle8) or ± LANGUAGE clause (Oracle8i)  

1/21/2011 Copyright 2001 Steven Feuerstein

PL/SQL Advanced Techniques - page 193

1. Identify/create external routine 


Prerequisite: O/S must support shared libraries Some useful routines are pre-built in C runtime library
± On Unix: /lib/libc.so ± On NT: <systemroot>\system32\crtdll.dll 

Building a shared library of your own requires knowledge of:
± Appropriate language (typically C) ± Compiler & linker

1/21/2011 Copyright 2001 Steven Feuerstein

PL/SQL Advanced Techniques - page 194

2. Create the Oracle library 

Syntax:
CREATE OR REPLACE LIBRARY <library name> AS '<full path to file>'; 

Assigns a programmer-defined alias to a specific shared library file Notes
± Requires CREATE LIBRARY pri ilege ± Does not alidate directory ± Can¶t use symbolic link 

1/21/2011 Copyright 2001 Steven Feuerstein

PL/SQL Advanced Techniques - page 195

3. Map the parameters
This can get complicated, because«
± Must pass extra parameters to designate:
» NULL/NOT NULL state » String length » Maximum allocated length

± Six choices of parameter mode
» » » » » » IN RETURN IN BY REFERENCE RETURN BY REFERENCE OUT IN OUT

These details are better suited for close reading«
PL/SQL Advanced Techniques - page 196

1/21/2011 Copyright 2001 Steven Feuerstein

Achieving PL/SQL Excellence Oracle8i New Features Autonomous Transactions Invoker Rights Model Row Level Security 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .page 197 .

   Autonomous Transactions The Invoker Rights Model Row level security 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .Oracle8i New Features  Oracle8i offers a number of PL/SQL-specific features that give you tremendous additional flexibility and capability. ± And the learning curve to take advantage of these features is generally not too steep.page 198 .

a COMMIT or ROLLBACK in any program in your session committed or rolled back all changes in your session. msg IN VARCHAR2) AS PRAGMA AUTONOMOUS_TRANSACTION. ± There was only one transaction allowed per connection. ± Any changes made within that block can be saved or reversed without affecting the outer or main transaction.page 199 .Autonomous Transactions  Prior to Oracle8i. you can now define a PL/SQL block to execute as an "autonomous transaction".  With Oracle8i. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . CREATE OR REPLACE PROCEDURE loginfo ( code IN PLS_INTEGER.

± Now you can avoid the complexities (need for ROLLBACK TO savepoints and so on).When to Use Autonomous Transactions  Reusable Application Components ± ATs are more or less required in the new distributed application architecture of the Internet.page 200 1/21/2011 Copyright 2001 Steven Feuerstein .  Logging Mechanism ± Commonly developers lot to database tables. software usage meter. etc. PL/SQL Advanced Techniques .  Tracing Code Usage ± Build retry mechanisms. which can cause all sorts of complications: your log entry becomes a part of your transaction. ± One component should not have any impact (esp.  Call functions within SQL that change the database. something like a COMMIT) on other components.

program ). EXCEPTION WHEN OTHERS THEN ROLLBACK. END. logger.tst PL/SQL Advanced Techniques . While we're at it.machine. COMMIT. text_in. BEGIN INSERT INTO logtab VALUES (code_in.pkg log81*. SYSDATE. rec. rec. let's add some session information. text_in IN VARCHAR2 ) IS PRAGMA AUTONOMOUS_TRANSACTION.sp log81.pkg retry. USER.tst retry.Logging with ATs  Don't forget that ROLLBACK in the exception section! CREATE OR REPLACE PACKAGE BODY log IS PROCEDURE putline ( code_in IN INTEGER.page 201 . END. USER. 1/21/2011 Copyright 2001 Steven Feuerstein Avoid interdependencies with the main transaction. SYSDATE.

The AT PRAGMA can be used only with individual programs and toplevel anonymous blocks.sql autontrigger*. ± Place the SET TRANSACTION statement in the outer transaction. ± You cannot tell by looking at the package spec if you are calling ATs or not -and this info is not available in the data dictionary.  Any changes committed in an AT are visible in the outer transaction.   The AT PRAGMA goes in the body of packages.Tips and Gotchas with ATs  An AT program must COMMIT or ROLLBACK before terminating. ± You can use the SET TRANSACTION ISOLATION LEVEL SERIALIZABLE to indicate that you do not want the changes visible until the outer transaction commits. or an error is raised. ± You cannot define an entire package as an AT. ± You cannot define a nested anonymous block to be an AT.sql 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . autonserial.page 202 .sql auton_in_sql.

it ran under the privileges of the account in which the program was defined. you can now decide at compilation time whether your program or package will execute in the definer's schema (the default) or the schema of the invoker of the code. ± This is called the « Definer Rights Model  With Oracle8i. ± This is called the « Invoker Rights Model PL/SQL Advanced Techniques .page 203 1/21/2011 Copyright 2001 Steven Feuerstein .The Invoker Rights Model  Prior to Oracle8i. whenever you executed a stored program.

page 204 . Note: Oracle built-in packages have long had the capability of running under the invoker's authority. Ignores roles and relies on directly-granted privileges. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . But it can be a source of confusion and architectural problems. OE Code Order_Mgt Place Cancel Sam_Sales Close Old Orders  OE Data X  Orders Cannot alter table directly.About Definer Rights  Allows you to centralize access to and control of underlying data structures.

unless you write code in the package to essentially recreate roles programmatically.page 205 ... each user has own copy of table(s). ± Can bypass 8i¶s ³fine-grained´ access features (see the DBMS_RLS package) ± Difficult to audit privileges  Sure would be nice to have a choice.it's all or nothing.and now you do! 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . requiring copy of stored module  Security ± No declarative way to restrict privileges on certain modules in a package -.Problems with Definer Rights  Deployment & maintenance ± Must install module in all remote databases where needed ± In some databases.

the objects referenced may well be different from those against which it compiled.. and must be at the package level. ± In other words.Oracle8i Invoker Rights Syntax  For top level modules: CREATE [ OR REPLACE ] <module type> [ AUTHID { DEFINER | CURRENT_USER } ] AS .page 206 . You could also create local. "dummy" objects. ± At run-time. Synonyms may be necessary if modules use object names not qualified by schema. do what it takes to get the code to compile.  1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .  For modules with separate spec and body.. AUTHID goes only in spec.

destroy(... modify destroy .. code."Reflection" Capability of Invoker Rights  With invoker rights.FROM accounts WHERE.).page 207 . you can execute code owned by another schema..acct_mgr. Central Code schema PACKAGE acct_mgr make AUTHID CURRENT_USER User/Data schema PROCEDURE mng_account IS BEGIN . END.... accounts table 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .. yet have all references to data structures "reflect back" into your own schema.

sql handy. the definer rights model is always applied to resolve the reference. Note: cannot use with wrapped code. only data ± When your stored code references another stored code element.  Information about the rights model is not available in the data dictionary What if you want to maintain a single version of your code for both pre-Oracle8i and Oracle8i installations. all other calls in stack are resolved according to definer rights.sql  1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . taking advantage of the invoker rights model whenever possible? ± A creative use of SQL*Plus substitution variables comes in very invdefinv. ± AUTHID CURRENT_USER is ignored.  Once a definer rights program is called.page 208 . oneversion. ± Both static and dynamic SQL is supported.Tips and Gotchas for Invoker Rights  Does not apply to code objects.

but you want their own directly-granted privileges to determine access.sql whichsch*.When to Invoke Invoker Rights  You want to reuse the same code among many users.sql 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . authid. ± Share a program that uses dynamic SQL (whether DBMS_SQL or the new native implementation) and you end up taking the most unexpected DDL and DML detours. National HQ Check City Statistics New York Schema stolenlives Chicago Schema stolenlives  Especially handy with dynamic SQL.page 209 .

Combining Invoker & Definer Rights  Rely on invoker rights to allow centralized code to work with schema-specific data.page 210 . Rely on definer rights to access centralized data from any schema.sql 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . HQ Chicago Check City Statistics  New York stolenlives Analyze Pattern stolenlives perpetrators perp.

page 211 .Row Level Security DBMS_RLS Row-Level Security 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .

DBMS_RLS. with which to implement automated row-level security (also referred to as "fine grained access control"). you could achieve this only partially through the use of views. The DBMS_RLS package (along with "system contexts") now allow you to do so in a foolproof manner. PL/SQL Advanced Techniques .Row-Level Security with DBMS_RLS  Oracle8i offers a new package. Prior to Oracle8i. Row Level Security  The establishment of security policies on (restricted access to) individual rows of a table.page 212   1/21/2011 Copyright 2001 Steven Feuerstein .

 Database Logon Triggers ± I want to make sure that when a person logs in. their context information is set properly.page 213 . 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .  Security Policy Packages ± You will need to write a package containing functions that establish the security policies to be applied to a particular table. the system context is a named set of attributevalue pairs global to your session.  DBMS_RLS ± Use programs in DBMS_RLS to associate your security policies with tables.Components Needed for RLS  System Contexts ± A new feature in Oracle8i.  Let's step through a simple example to see how all these pieces tie together.

No more for-profit hospitals pulling billions of dollars out of the system. no more private insurance companies soaking up 30 cents on the dollar. clinic and regulator. The main tables are patient. popular uprising in the United States has forced the establishment of a national healthcare system.page 214 .A National Health Care System  The year is 2010.sql  1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .  We need a top-notch. all pregnant women receive excellent prenatal care. all children are vaccinated. doctor. ± A massive. fgac. ± Regulators can only see patients who reside in the same state. Here are some rules: ± Doctors can only see patients who are assigned to their clinic. ± Patients can only see information about themselves. highly secure database for NHCS.

and create a procedure that will set the context attributes (type and ID) upon login. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . c_person_id_attr.SET_CONTEXT ( 'patient_restriction'. doc_rec doc_cur%ROWTYPE. DBMS_SESSION. FETCH doc_cur INTO doc_rec.SET_CONTEXT ( 'patient_restriction'. c_person_type_attr. DBMS_SESSION. 'DOCTOR'). See CURSOR doc_cur IS fgac. END.Set the Context  Define a context in the database. doc_rec. CREATE CONTEXT patient_restriction USING nhc_pkg. PROCEDURE set_context IS This is a simplification. BEGIN OPEN doc_cur.sql for logic that identifies SELECT doctor_id FROM doctor different types of people and WHERE schema_name = USER.page 215 .doctor_id). sets the context accordingly.

information for this retval VARCHAR2(2000). connection. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .page 216 . name_in VARCHAR2) RETURN VARCHAR2 IS l_context VARCHAR2(100) := Extract the context SYS_CONTEXT (c_context. FUNCTION person_predicate ( schema_in VARCHAR2. BEGIN IF l_context = 'DOCTOR' THEN retval := 'home_clinic_id IN (SELECT home_clinic_id FROM doctor We need a different string WHERE doctor_id = SYS_CONTEXT (''' || to modify the WHERE c_context || '''. person. c_person_type_attr).Define the Predicate  A predicate is a string that will be appended to the WHERE clause of the table to which this security policy is associated (see next page). ''' || clause for each type of c_person_id_attr || '''))'.

'patient'.Create the Security Policy  Use the DBMS_RLS.person_predicate'. 'patient_privacy'. BEGIN DBMS_RLS. 'SELECT. ± The following procedure call specifies that the WHERE clause of any query.ADD_POLICY procedure.PATIENT table will be modified by the string returned by the person_predicate function of the SCOTT.ADD_POLICY OBJECT_SCHEMA OBJECT_NAME POLICY_NAME FUNCTION_SCHEMA POLICY_FUNCTION STATEMENT_TYPES END.page 217 .DELETE'). update or delete against the SCOTT. 'nhc_pkg. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . 'SCOTT'.UPDATE. ( => => => => => => 'SCOTT'.nhc_pkg package.

CREATE OR REPLACE TRIGGER set_id_on_logon AFTER LOGON ON DATABASE BEGIN nhc_pkg.page 218 . END. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.Create Logon Trigger.set_context.PUT_LINE ( 'Error ' || SQLCODE || ' setting context for ' || USER'). fgac.sql Exception handling in trigger is critical! If you allow an exception to go unhandled. logon is disabled. Setting Context  By setting the context in the logon trigger. we guarantee that the context is set (and the predicate applied) no matter which product is the entry point to Oracle.

PL/SQL Advanced Techniques .Chris Silva .IL Context Information for "CSILVA": Type: PATIENT ID: Predicate: schema_name = 'CSILVA' Patients Visible to "CSILVA": CSILVA .Queries Transparently Filtered  What you see is determined automatically by who you are.Veva Silva . 'person_id')) Patients Visible to "SWALLACE": CSILVA .IL 1/21/2011 Copyright 2001 Steven Feuerstein Patient sees only himself.IL VSILVA . Predicate: home_clinic_id IN (SELECT home_clinic_id FROM doctor WHERE doctor_id = SYS_CONTEXT ('patient_restriction'.page 219 . Context Information for "SWALLACE": Type: DOCTOR Doctor sees only her ID: 1060 patients.Chris Silva .

 ± You learn what you need to get the job done. It's so easy to fall into a rut with a programming language.... April..and play a new tune with PL/SQL! 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .page 220 .. Jump out of your rut ... March.. and you use only what you know. February.Take Full Advantage of PL/SQL! January.. May..

page 221 . If time permits«)     UTL_FILE ± file IO DBMS_JOB ± Job scheduling DBMS_PIPE ± Pipe-based communication DBMS_UTILITY ± the kitchen sink package 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .k..a.Achieving PL/SQL Excellence Appendices (a.

..page 222 . Physical Files 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .Built-in Packages: UTL_FILE UTL_FILE Server-side File I/O Application FOPEN GET_LINE PUT_LINE .

UTL_FILE: Server-side I/O  Allows you to read from and write to operating system files on the database server. ± Maximum of 1023 bytes per line (read or write) until Oracle 8..   But you can read lines from a file and write lines to a file.. ± No higher-level file operations supported (change privileges. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . A "version 1" (fairly primitive) utility. random access to contents).5. when it jumps to 32K. delete.page 223 . copy. no use of environmental variables).0. ± Limitations on files you can access (no mapped files.

Puts formatted text into the buffer PL/SQL Advanced Techniques .page 224 1/21/2011 Copyright 2001 Steven Feuerstein .UTL_FILE Module Outline FCLOSE FCLOSE_ALL FFLUSH FOPEN GET_LINE IS_OPEN NEW_LINE PUT PUT_LINE PUTF Close the specified file Close all open files in your session Flush all data from the UTL_FILE buffer to your file Open a file Get the next line from a file Returns TRUE if the file is open (sort of) Insert a new line character in file at the end of current line Puts text into the UTL_FILE buffer Puts text and new line character into UTL_FILE buffer.

± No single or double quotes around directory. utl_file_dir = * Allows read & write for any directory.Authorizing Directory Access  Oracle requires you to list explicitly those directories you wish to be able to read/write with UTL_FILE. PL/SQL Advanced Techniques .page 225 Allows read & write for current directory. ± Use a separate entry for each directory (and subdirectory.  Follow these rules to avoid many headaches. no trailing delimiter. there is no subdirectory recursion). ± You do this by adding lines to the instance parameter file. 1/21/2011 Copyright 2001 Steven Feuerstein . utl_file_dir = /tmp utl_file_dir = /accounts/newdev  And don't do either of the following: utl_file_dir = .

PUT_LINE (fid. and then run the following test script (it can't get much simpler than this): DECLARE fid UTL_FILE. restart your database.Test UTL_FILE Access  About the hardest part to working with UTL_FILE is simply getting started. END. modify your initialization file.FCLOSE (fid). 'W').txt'.FOPEN ('c:\temp'.FILE_TYPE. BEGIN /* Change the directory name to one to which you at least || THINK you have read/write access.tst  1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . So before you write anything fancy. UTL_FILE. 'hello'). UTL_FILE. 'test. / utlfile. */ fid := UTL_FILE.page 226 .

txt'..Opening a File DECLARE fid UTL_FILE. Not much of a test. 'W'). 'W' for Write and 'A' for Append. Test to see if file is open with the IS_OPEN function.page 227 . this function simply returns TRUE if the file handle's id field is NOT NULL. END.FILE_TYPE. ± In actuality. name and operation type.FOPEN ('c:\temp'.. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .  The FOPEN function returns a record ("file handle") based on the UTL_FILE. ± Types are 'R' for Read.FILE_TYPE. 'test. ± Currently contains a single ID field. BEGIN fid := UTL_FILE.   Maximum of 10 files may be opened in each user session.  Specify file location.

0.sp 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . 'test.Reading from a File DECLARE fid UTL_FILE. END. Lines in the file cannot be longer than 1023 bytes in length.FILE_TYPE. the ceiling is raised to 32K.txt'. ± You might want to build your own GET_LINE which handles the exception and returns an EOF Boolean status flag.  The NO_DATA_FOUND exception is raised if you read past the end of the file. UTL_FILE.FCLOSE (fid).5 and above. myline).GET_LINE (fid. 'R'). ± In Oracle8 Release 8. UTL_FILE. getnext.FOPEN ('c:\temp'.page 228 . BEGIN fid := UTL_FILE.   Can only read from a file opened with the "R" mode.

± The file buffers are automatically flushed when you close a file or exit your session.  Call FFLUSH to make sure that everything you have written to the buffer is flushed out to the file.PUT_LINE (fid. 'is so much fun').PUT (fid. UTL_FILE. UTL_FILE. allowing for some formatting.FCLOSE (fid). 'test. '&1'). ± PUTF is like the C printf program.PUTF (fid. ' that I never\nwant to %s'. PL/SQL Advanced Techniques .Writing to a File DECLARE fid UTL_FILE.FILE_TYPE.FOPEN ('c:\temp'. UTL_FILE. UTL_FILE. 'W').txt'. UTL_FILE is so much fun that I never want to stop Resulting Text  You can use PUT. BEGIN fid := UTL_FILE. 'UTL_FILE'). END. PUT_LINE or PUTF.page 229 1/21/2011 Copyright 2001 Steven Feuerstein .

txt'.  If you do not close the file. you will not see the data you have (supposedly) written to that file. PL/SQL Advanced Techniques . You should close files in exception handlers to make sure that files are not left "hanging" open. UTL_FILE.FILE_TYPE. UTL_FILE.FCLOSE (fid). EXCEPTION WHEN UTL_FILE.FCLOSE (fid). You can close a single file with FCLOSE or all open files with FCLOSE_ALL.GET_LINE (fid. BEGIN fid := UTL_FILE. 'test.READ_ERROR THEN UTL_FILE.page 230   1/21/2011 Copyright 2001 Steven Feuerstein .Closing a File DECLARE fid UTL_FILE.FOPEN ('c:\temp'. 'R'). END. myline).

1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . ± UTL_FILE-named exceptions in other cases. EXCEPTION.page 231 .  UTL_FILE relies on a combination of user-defined exceptions and STANDARD exceptions to communicate errors. EXCEPTION.Error Handling in UTL_FILE PACKAGE UTL_FILE IS invalid_path invalid_mode invalid_filehandle invalid_operation read_error write_error internal_error END.  You have to take special care to trap and handle the named exceptions. ± They all share a common SQLCODE of 1. EXCEPTION. EXCEPTION. ± NO_DATA_FOUND when you try to read past the end of the file. EXCEPTION. EXCEPTION. EXCEPTION.

c_invalid_operation).READ_ERROR THEN recNgo (PLVfile. utlflexc.c_write_error). RAISE.Recommended Exception Section EXCEPTION WHEN UTL_FILE.sql  Trap locally by name.INVALID_OPERATION THEN recNgo (PLVfile. WHEN UTL_FILE.c_internal_error). RAISE. Re-raise exception if you want it to propagate from that block. WHEN UTL_FILE. RAISE. PL/SQL Advanced Techniques . RAISE. RAISE. WHEN UTL_FILE.page 232  1/21/2011 Copyright 2001 Steven Feuerstein . RAISE. WHEN UTL_FILE.c_read_error). translating the generic user-defined exception into an understandable message.INVALID_FILEHANDLE THEN recNgo (PLVfile.INTERNAL_ERROR THEN recNgo (PLVfile. WHEN UTL_FILE.INVALID_PATH THEN recNgo (PLVfile.c_invalid_path). END.c_invalid_filehandle). RAISE. WHEN UTL_FILE.WRITE_ERROR THEN recNgo (PLVfile.c_invalid_mode).INVALID_MODE THEN recNgo (PLVfile. record the error.

Background Process DBA_JOBS Oracle Job Queue Subsystem 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .page 233 ...Built-in Packages: DBMS_JOB DBMS_JOB Scheduled Execution of Stored Procedures Application SUBMIT RUN REMOVE .

Made its debut in PL/SQL Release 2.1. Schedule regular maintenance on instances.page 234 . ± Spawn background processes to avoid blocking client process. Create a listener program to poll the contents of a pipe and take action. Schedule large batch jobs to run on "off hours". but only ³publicly available´ and supported in PL/SQL Release 2.Overview of DBMS_JOB  DBMS_JOB provides an API to the Oracle job queues. Built by Oracle to support snapshots and replication. which in turn offers job scheduling capabilities within the Oracle Server. You can use DBMS_JOB to: Replicate data between different database instances.2. ± ± ± ±    1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .

page 235 CHANGE INTERVAL ISUBMIT NEXT_DATE REMOVE RUN SUBMIT USER_EXPORT WHAT 1/21/2011 Copyright 2001 Steven Feuerstein . Removes the job from the queue. Changes one or all attributes of a job. Changes the job string of a job. Submits a job to the queue returning a unique job number. Changes the interval between executions of a job. Forces immediate execution of the specified job number. PL/SQL Advanced Techniques .DBMS_JOB Module Outline BROKEN Marks the job as either FIXED or BROKEN. Returns the job string for a job number. Broken jobs will not run as scheduled. Submits a job to the queue using a predefined job number. Changes when a queued job will run.

SUBMIT (job#. PL/SQL Advanced Techniques . instead of having DBMS_JOB generate one for you. 'calculate_totals.ISUBMIT and supply the job number. while the interval is a string (this is dynamic PL/SQL!)  You can also call DBMS_JOB. I run calculate_totals immediately and then on a daily basis thereafter.page 236 1/21/2011 Copyright 2001 Steven Feuerstein .Submitting a Job DECLARE job# BINARY_INTEGER.'.  A job is a call to a stored procedure or an anonymous block ± It must end with a semi-colon and can contain ³hard-coded´ arguments. 'SYSDATE + 1'). Notice that the start time is a DATE expression. BEGIN DBMS_JOB.  When you submit a job. END. and then the job¶s execution interval (frequency of execution). SYSDATE. you specify the date on which it should next execute. ± In the above example.

estimate_percent=>50). /  This block submits a job that uses a built-in procedure. BEGIN DBMS_JOB.null. what => 'DBMS_DDL. next_date => TRUNC (SYSDATE + 1). interval => 'TRUNC(SYSDATE+1)' ). p.l (v_jobno). END.Submit Job Example DECLARE v_jobno INTEGER.''ESTIMATE''.''TENK''' || '. PL/SQL Advanced Techniques .'.page 237 1/21/2011 Copyright 2001 Steven Feuerstein .ANALYZE_OBJECT. DBMS_DDL.ANALYZE_OBJECT ' || '(''TABLE''.submit ( job => v_jobno. to analyze a specific table every evening at midnight.''LOAD1''.

ISUBMIT (2.ISUBMIT (job => 1 .' .'.null).ISubmit Job Example BEGIN DBMS_JOB.ISUBMIT(3. numbered 1. ± Job 3 is a PL/SQL block which does nothing. DBMS_JOB.DBMS_JOB.120). ± Job 1 passes a string and number into procedure MY_JOB1. DBMS_JOB. executes immediately.2. and will be removed from the queue automatically.what => 'my_job1(''string_parm_value''. executes for the first time tomorrow and every 10 minutes thereafter.'SYSDATE+10/1440').page 238 . 'my_job2(date_IN=>SYSDATE).interval => 'SYSDATE +1'). END.'BEGIN null.SYSDATE+1. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . and 3. /  This block submits three jobs to the job queue.next_date => SYSDATE + 1/24 .' . runs it in one hour and executes every day thereafter. ± Job 2 passes a date into procedure MY_JOB2.SYSDATE. END.

''MONDAY'') + 9/24' 'TRUNC (LEAST ( NEXT_DAY (SYSDATE. Every hour Every Sunday at 2 AM First Monday of each quarter. ± Since it's a string. Wednesday and Friday at 6 PM 'SYSDATE + 1/24' 'NEXT_DAY (TRUNC (SYSDATE). you must use 2 single quotes to embed strings. ± Use date arithmetic to request intervals smaller than a day.page 239 + 1/21/2011 Copyright 2001 Steven Feuerstein . NEXT_DAY (SYSDATE. ''WEDNESDAY''). ''MONDAY''). ''FRIDAY''))) + 18/24' PL/SQL Advanced Techniques . 3). at 9 AM Every Monday. ''Q''). NEXT_DAY (SYSDATE.Specifying Job Times & Frequencies  Probably the most complicated part of using DBMS_JOB is to get the string expression of the job interval right. ''SATURDAY'') 2/24' 'NEXT_DAY ( ADD_MONTHS (TRUNC (SYSDATE.

± Only if the job was submitted from same schema BEGIN FOR rec IN (SELECT * FROM USER_JOBS) LOOP DBMS_JOB.ISUBMIT. END LOOP. retaining current job number. ± Performs an implicit COMMIT in current session.REMOVE (rec. Remove all jobs for current schema.  Export jobs from the queue.  Run a job immediately.sql 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . expjob.job).RUN (my_job#). ± Produces a string that can be used to recreate an existing job in the job queue. DBMS_JOB. ± Uses DBMS_JOB.Other Job Queue Operations  Remove a job from the queue.page 240 .

DBA_JOBS and USER_JOBS views.this_date . SELECT jr.what job_id username start_date job_definition jr j s showjobs. ± The following query blends job information with session information to display currently-executing jobs.username .job .DBA_JOBS .page 241 .sid = jr.job = j.job ORDER BY jr.V$SESSION WHERE s. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .sql FROM DBA_JOBS_RUNNING .Job Queue Views  You can also view the job queue by looking at the DBA_JOBS_RUNNING. who owns them and when they began.sid AND jr.jr.this_date.

1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . ± job_queue_interval=N where N is the interval in seconds to check the job queue. therefore.Setting up the Job Facility  Make sure that the correct access is set up for the DBMS_JOB package.  You will need to set three parameters in the init. The valid range is 0 through 36.page 242 .ora (initialization) file for your database instance: ± job_queue_processes=N where n is the number of concurrent background processes permitted. You will have to take special DBA action if you want to restrict who can run jobs. ± The default is PUBLIC access. The valid range is 1 to 3600 (a maximum. of one hour).

 To avoid unexpected and unhandled failures of scheduled jobs: ± Always use the RUN built-in to execute your job in a ³test´ mode. if your failure raises an unhandled exception. ± Always include a WHEN OTHERS exception handler in your job program which traps any and all problems and automatically sets the job status to broken. ± Do you want it to try 16 times? ± In addition.page 243 . 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . Then you can go ahead and submit it.Error Handling with DBMS_JOB  What if your stored procedure fails? ± After 16 attempts. it may cause the background processes to fail and no longer run any jobs at all. the job facility will mark your job as broken.

END.. ± Uses a call to BROKEN to set the status of the job to ³broken´. You can go in and fix the problem.job (µcalc_totals¶) DBMS_JOB. ± Now the job facility will not try to run this program again.BROKEN (job#. µFAIL¶).log (µcalc_totals¶. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . ± Obtains the job number from a packaged function by passing the name of the procedure. ± Calls log program of package to record that failure took place. EXCEPTION WHEN OTHERS THEN job# := job_pkg. TRUE). job_pkg..sql  The WHEN OTHERS exception handler of the calc_totals procedure traps any kind of failure. spacelog.Stopping the Job When It Fails PROCEDURE calc_totals IS BEGIN .sql showspc.page 244 .

   1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques ."Good to Knows" for DBMS_JOB  You may find it useful to always wrap your stored procedure call (the what) inside a BEGIN-END block. You can use the DBMS_IJOB to manage the jobs of other users. perform a COMMIT after your submit.page 245 .  You will need to fully-qualify all database links (with user name and password) to get them to work properly. difficult to reproduce behavior at times with "straight" procedure calls. ± We've noticed some aberrant. When a job runs. ± DBMS_JOB only allows you to modify characteristics and behavior of jobs submitted by the current schema. If you find that you submit a job to run immediately and it does not start. it picks up the current execution environment for the user.

page 246 .Built-in Packages: DBMS_PIPE DBMS_PIPE Inter-session Communication 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .

± Interface PL/SQL-database activities with operating system functions and programs written in other languages. ± More sophisticated debugging inside PL/SQL programs (work around fundamental limitations of DBMS_OUTPUT). ± Perform and commit DML in a separate transaction space from your main transaction.DBMS_PIPE Overview  Allows communication between different Oracle sessions through a pipe in the RDBMS Shared Global Area. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .  Uses for DBMS_PIPE include: ± Parallelization of program execution. Oracle uses database pipes to parallelize database operations. You can parallelize your own code.page 247 . ± Operates outside of database transaction limitations.

page 248 .Architecture of DBMS_PIPE Shared Global Area ³Sue´ ³Bob´ Message Buffer Message Buffer Session A  Session B A pipe is a named object that uses the System Global Area to provide a non-transaction based conduit of information. They are reserved for Oracle use). using a maximum of 4096 bytes. which can be composed of one or more separate packets. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . ± The pipe sends/receives a message. ± Names can be up to 128 chars long (do not use names beginning with ³ORA$´.

1/21/2011 Copyright 2001 Steven Feuerstein pipex1. ± You can wait for up to 1000 days for a message. ± Separate out the individual packets in the message (again: string.  Unpack the message packets and take action. date. ± Each packet can be a string. ± If there isn¶t currently room in the pipe.  Receive a message from that pipe.page 249 . number.Processing Flow of DBMS_PIPE  Construct a message from packets of information. you can wait for up to 1000 days (or 86400000 seconds) for the pipe to be cleared.  Send the message to a named pipe. ± This is the default. ± There is just one message buffer per session.sql pipex2. so you should always specify a timeout period. date or number). ROWID or RAW.sql PL/SQL Advanced Techniques .

1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . REMOVE_PIPE RESET_BUFFER Removes a pipe explicitly created via CREATE_PIPE. RECEIVE_MESSAGE Receives a message from pipe and copies to local buffer. making it a candidate for removal with a LRU algorithm. SEND_MESSAGE Sends contents of message buffer to the specified pipe. Clears your buffer so that PACK_MESSAGE and UNPACK_MESSAGE can work from the first item.DBMS_PIPE Module Outline Module Name CREATE_PIPE Description Creates a PUBLIC or PRIVATE pipe. PACK_MESSAGE Packs an item into the message buffer for your session. NEXT_ITEM_TYPE Returns the datatype of the next item in the piped message.page 250 . UNIQUE_SESSION_NAME Returns name that is unique among all sessions in the database. PURGE Empties the contents of a pipe into your local buffer freeing it for removal. UNPACK_MESSAGE Unpacks the next item from the local message buffer and deposits it into the specified local variable.

maxpipesize => 20000. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .CREATE_PIPE ( pipename => 'bbs'. ± Specify TRUE for private argument of CREATE_PIPE.  A public pipe is accessible as long as you know its name. private => TRUE). BEGIN stat := DBMS_PIPE. ± Send messages to non-existent pipe implicitly create it. ± Implicitly-created pipes are always public. PROCEDURE newpipe IS stat INTEGER.page 251 .Creating Public and Private Pipes  There are two ways to create pipes: implicitly and explicitly.  An explicit pipe can be private (accessible only to sessions with matching userID or SYSDBA privileges). ± Use CREATE_PIPE to create a pipe explicitly.

waiting up to 1 minute. Send to "monthly" pipe. pipe_stat := DBMS_PIPE. FOR month_num IN 1 . 12 LOOP DBMS_PIPE.PACK_MESSAGE ( total_sales (month_num)). Status of 0 means message was sent.Sending a Message Provide pipe name. expanding pipe size to 40 Kbytes. FUNCTION send_message (pipename IN VARCHAR2. 1/21/2011 Copyright 2001 Steven Feuerstein Fill your message buffer with packets of data. timeout IN INTEGER DEFAULT maxwait. 60. 10 * 4096). maxpipesize IN INTEGER DEFAULT 8192) RETURN INTEGER. END LOOP. seconds you will wait. IF pipe_stat != 0 THEN RAISE could_not_send.. PL/SQL Advanced Techniques . but not smaller). and new max pipe size (you can make it bigger.page 252 .SEND_MESSAGE ( µmonthly¶.

timeout IN INTEGER DEFAULT maxwait) RETURN INTEGER. ± Specify pipe and number of seconds you will wait before you time out. ± You need to know the datatype of packet or check it using NEXT_ITEM_TYPE. PROCEDURE unpack_message (item OUT VARCHAR2). PROCEDURE unpack_message (item OUT DATE). PROCEDURE unpack_message (item OUT NUMBER).  Then you call UNPACK_MESSAGE to extract individual packets from the message.page 253 .  First you pull the message from the pipe and place it in buffer with RECEIVE_MESSAGE. ± Pipe status of 0 means the message was read successfully.Receiving and Unpack a Message FUNCTION receive_message (pipename IN VARCHAR2. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .

ELSE RAISE_APPLICATION_ERROR ( Stop process if -20000.'). LOOP pipe_status := DBMS_PIPE. 'Production data unavailable.A Pipe-based Listener Program  Program wakes up every N seconds to read the data from the pipe and analyze results from assembly line (an intentional "infinite loop"!). Wait up to N prod_total NUMBER. END. seconds for the BEGIN next report. analyze_production (SYSDATE. DBMS_PIPE.page 254 1/21/2011 Copyright 2001 Steven Feuerstein . data not received. every_n_secs). PL/SQL Advanced Techniques .UNPACK_MESSAGE (prod_total). PROCEDURE analyze_assembly_data (every_n_secs IN INTEGER) IS pipe_status INTEGER.RECEIVE_MESSAGE ( 'production'. END IF. prod_total). If I got something. pass it on to the IF pipe_status = 0 computation THEN program. END LOOP.

you have to make sure that you unpack a packet into the right kind of variable.page 255 . Returns one of the following values: Value 0 6 9 11 12 23 Description or Data type No more items in buffer NUMBER VARCHAR2 ROWID DATE RAW dbpipe. ± Or you use the built-in NEXT_ITEM_TYPE to tell you in advance the datatype of the next packet in the message and take appropriate action.Unpacking the Message FUNCTION next_item_type RETURN INTEGER. Either: ± You know the datatype and therefore can ³hard-code´ the correct variable into the call to UNPACK_MESSAGE. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .sql dbpipe.tst  Since a message can be composed of packets of different datatypes.

 Without pipes.Parallelizing Your Code with Pipes  Oracle uses DBMS_PIPE to improve RDBMS performance. ± The CEO is decidedly unhappy about the delay. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .page 256 . but are not dependent on each other. In order to do so I must first compute total sales. ± These programs each take 15 minutes.  Suppose I want to calculate my net profit. I must execute them sequentially and incur an elapsed time of 45 minutes before I calculate the profits. total office expenses and total compensation. you can do the same for your application if: ± You have multiple CPUs available. ± You have processes which can run in parallel.

Sequential vs.page 257 . Parallel Execution Sequential Execution: Maximum Elapsed Time S t a r t E n d Process A Process B Process C Parallel Execution: Minimum Elapsed Time Start Process A Process B Process C End 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .

 The ³kick off´ programs pass their messages to separate pipes. calculate_net_profits.in a muchdecreased elapsed time. PL/SQL Advanced Techniques .  The ³wait´ program waits till it receives a message from each program.page 258 1/21/2011 Copyright 2001 Steven Feuerstein . ± Other programs running in the background grab the messages and start their corresponding calculation program. ± When each program is complete. it puts a message (perhaps even a value) into the pipe. Then net profits can be computed -. kick_off_exp_calc. wait_for_confirmation.Parallelizing PL/SQL Execution BEGIN kick_off_sales_calc. kick_off_totcomp_calc. END.

page 259 . IF stat = 0 THEN lots_of_number_crunching.SEND_MESSAGE (µsales¶). END. PROCEDURE calculate_sales IS stat INTEGER. PL/SQL Advanced Techniques . 1/21/2011 Copyright 2001 Steven Feuerstein Send message to start calculations. BEGIN stat := DBMS_PIPE.Code to Kick Off and Calculate PROCEDURE kick_off_sales_calc IS stat INTEGER. DBMS_PIPE.PACK_MESSAGE (sales$). calculate sales. stat := DBMS_PIPE. stat := DBMS_PIPE. END IF. stat := DBMS_PIPE. BEGIN DBMS_PIPE.PACK_MESSAGE (NULL). Receive the year.SEND_MESSAGE (µsales¶).SEND_MESSAGE (µsales¶). END. and send back the results.PACK_MESSAGE (1995). ELSE DBMS_PIPE.RECEIVE_MESSAGE (µsales¶).

page 260 .comp$. The order in which you wait is insignificant. parallel. Wait for all calculations to finish.offexp$ . BEGIN stat := DBMS_PIPE.RECEIVE_MESSAGE (µsales¶).Waiting for Confirmation PROCEDURE wait_for_confirmation IS stat INTEGER. Perform final calculation. stat := DBMS_PIPE. END. DBMS_PIPE.UNPACK_MESSAGE (sales$).RECEIVE_MESSAGE (µcomp¶).UNPACK_MESSAGE (comp$). END. DBMS_PIPE.RECEIVE_MESSAGE (µoffexp¶).sql 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . stat := DBMS_PIPE. PROCEDURE calculate_net_profits IS BEGIN net_profits := sales$ .UNPACK_MESSAGE (offexp$). DBMS_PIPE.

in-memory cache.pkg p_and_l. syscache.pkg  Implementation of a system-wide. ± Demonstrates the use of toggles and switches in packages.tst 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . obtains the data. ± The requester reads the information from the pipe. ± A listener program grabs the request (including the return pipe name).page 261 .pkg syscache. watch.Other DBMS_PIPE Examples  Simple trace package that sends it output either to screen or to pipe. and sends it to the pipe. ± A request for data is passed to a "central" pipe.

page 262 . A µgrab-bag¶ of miscellaneous operations SCHEMA 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques ..Built-in Packages: DBMS_UTILITY DBMS_UTILITY Application GET_TIME GET_HASH_VALUE FORMAT_CALL_STACK ..

Returns hash value for string. Gets block number part of data block address.DBMS_UTILITY Module Outline ANALYZE_DATABASE ANALYZE_PART_OBJECT Analyze objects in database Runs ANALYZE TABLE or ANALYZE INDEX for each partition of the object (Oracle8).pkg COMMA_TO_TABLE COMPILE_SCHEMA DATA_BLOCK_ADDRESS_BLOCK DATA_BLOCK_ADDRESS_FILE DB_VERSION EXEC_DDL_STATEMENT FORMAT_CALL_STACK FORMAT_ERROR_STACK GET_HASH_VALUE 1/21/2011 Copyright 2001 Steven Feuerstein .pkg dbparm. Gets file number part of data block address. PL/SQL Advanced Techniques . Returns execution call stack. Parses comma-delimited list to index-by table.page 263 dbver. Returns error stack. Returns database version (Oracle8) Executes DDL statement (Oracle8). Recompile INVALID objects in specified schema.

Resolves name of object into component parts. Parses string object designator into components. Returns platform and version of database.page 264 . cont. GET_PARAMETER_VALUE GET_TIME IS_PARALLEL_SERVER MAKE_DATA_BLOCK_ADDRESS NAME_RESOLVE NAME_TOKENIZE PORT_STRING TABLE_TO_COMMA Retrieves value of database parameter (Oracle8). Returns TRUE if in parallel server mode. Returns "current time" down to hundredth of second. Converts list (in index-by-table) of elements into a comma-delimited list (string).DBMS_UTILITY Module Outline. Creates data block address from block & file numbers. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .

 Compare results from consecutive calls to GET_TIME to determine the elapsed time of PL/SQL code execution. ± Useful when analyzing individual PL/SQL programs.GET_TIME. DBMS_OUTPUT. especially those that run in sub-second time.PUT_LINE (DBMS_UTILITY. calc_totals.GET_TIME . Basic steps necessary to convert GET_TIME into a performance analysis tool. ± SYSDATE only reflects times down to the nearest second.page 265 1/21/2011 Copyright 2001 Steven Feuerstein . DECLARE v_start BINARY_INTEGER. END. so GET_TIME offers significant additional granularity. BEGIN v_start := DBMS_UTILITY.Sub-Second Timings with GET_TIME  GET_TIME returns the number of 100ths of seconds that have elapsed since an arbitrary point in time.v_start). PL/SQL Advanced Techniques .

reset_in IN BOOLEAN := TRUE). END. PROCEDURE capture ( context_in IN VARCHAR2 := NULL) PROCEDURE show_elapsed (prefix_in IN VARCHAR2 := NULL.page 266 . Clean and lean timing code ovrhead. BEGIN PLVtmr. adjust_in IN NUMBER := 0.capture.sps plvtmr. calc_totals.sql plvtmr. PROCEDURE set_factor (factor_in IN NUMBER). END PLVtmr. PROCEDURE turn_off.spb 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques . PLVtmr.show_elapsed.Building a Layer Over GET_TIME Partial package specification PACKAGE PLVtmr IS PROCEDURE turn_on.

END. ± Most recent program at beginning of "report".COMPANY_TYPE procedure STEVEN.VALIDATE_REQUEST function STEVEN. 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques .PUT_LINE ( DBMS_UTILITY. ± Does not show package elements. ----.FORMAT_CALL_STACK).page 267 .CALC_NET_WORTH anonymous block  "Little known facts" about FORMAT_CALL_STACK: ± Contains embedded new-line characters.Accessing the Execution Call Stack Use in the exception section to show context of error.PL/SQL Call Stack ----object line object handle number name 88ce3f74 88e49fc4 88e49390 88e2bd20 8 2 1 1 package STEVEN. EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT. equivalent to CHR(10). only the package name.

startpos INTEGER := 1. startpos := next_newline + 1. END.sps DBMS_OUTPUT.startpos + 1).page 268 1/21/2011 Copyright 2001 Steven Feuerstein . BEGIN stk := DBMS_UTILITY.Accessing Call Stack Contents  The call stack length can easily exceed 255 bytes.FORMAT_CALL_STACK || CHR(10). CHR(10).sp dispcs. dispcs. which means you cannot pass it to DBMS_OUTPUT directly. use a loop to read through the stack. END LOOP. next_line VARCHAR2(255). EXIT WHEN next_newline = 0. startpos. next_line := SUBSTR ( stk. next_newline INTEGER. LOOP next_newline := INSTR (stk. Instead. CREATE OR REPLACE PROCEDURE dispcs IS stk VARCHAR2(10000). next_newline . PL/SQL Advanced Techniques .tst callstack.pkg plvcs. startpos. 1).PUT_LINE (next_line).

for encapsulation! showcomp.Resolving Names of Stored Code  Code names have many components.NAME_RESOLVE (name IN VARCHAR2.pkg 1/21/2011 Copyright 2001 Steven Feuerstein PL/SQL Advanced Techniques ..page 269 .. context IN NUMBER.  Possible "Part 1" Types 5 7 8 9 Synonym Procedure Function Package What a chore! All those arguments. see it as an opportunity. the way they are attached also follows a complicated syntax. part1_type OUT NUMBER... object_number OUT NUMBER).but don't see it as a problem. part1 OUT VARCHAR2. dblink OUT VARCHAR2. ± Use NAME_RESOLVE to break down an identifier string into its components easily. PROCEDURE DBMS_UTILITY. schema OUT VARCHAR2. part2 OUT VARCHAR2.sp snc.

Sign up to vote on this title
UsefulNot useful