Gee Whiz!

New PL/SQL Toys in Oracle10g
Steven Feuerstein steven@stevenfeuerstein.com www.quest.com, www.qnxo.com, www.oracleplsqlprogramming.com
Copyright 2004-2005 Steven Feuerstein - Page 1

Software used in presentation 

You can download all my training materials and demonstration scripts from:
http://oracleplsqlprogramming.com/resources.html 

All scripts I run may be obtained from:
http://oracleplsqlprogramming.com/downloads/demo.zip
name of file

Copyright 2004-2005

Steven Feuerstein - Page 2

 Oh. yes.Page 3 . ± Alternative quoting mechanism ± Regular expressions Copyright 2004-2005 Steven Feuerstein .New but not overwhelming (learning curve-wise)  PL/SQL gets a whole lot faster ± and you don't have to lift a finger  The compiler now tells you about problems in your code  DBMS_UTILITY..  Nested table unveil their MULTISET-edness.. and then there are.FORMAT_ERROR_BACKTRACE  FORALL is lots more flexible.

Wow! An optimizing compiler!  Yes. [default] ± 1 Smaller scale change.Page 4 . maximum possible code transformations. less impact on compile times ± 0 Pre-10g compilation without optimization ALTER SESSION SET PLSQL_OPTIMIZE_LEVEL = 0.  You can choose the level of optimization through the plsql_optimization_level setting: ± 2 Most aggressive. ± Possible rearrangements to the code itself (under the covers). Copyright 2004-2005 Steven Feuerstein . the PL/SQL compiler now has the ability to automatically optimize your code. biggest impact on compile time.

" allowing you to recompile later using REUSE SETTINGS.Page 5 .  All compiler settings for modules are available in the USER_PLSQL_OBJECT_SETTINGS view. When you recompile a particular module with non-default settings.  and then: ALTER PROCEDURE bigproc COMPILE REUSE SETTINGS. the settings will "stick. Copyright 2004-2005 Steven Feuerstein .Optimizing compiler details  Oracle retains optimizer settings on a module-bymodule basis. For example: ALTER PROCEDURE bigproc COMPILE PLSQL_OPTIMIZE_LEVEL = 0.

sql Copyright 2004-2005 Steven Feuerstein .sql 10g_optimize_cfl.Cursor FOR Loop . ± You are retrieving many rows and cannot afford to use up the memory (large numbers of users). or BULK COLLECT?  Why would you ever use a cursor FOR loop (or other LOOP) now that you can perform a BULK COLLECT? ± If you want to do complex processing on each row as it is queried ± and possibly halt further fetching..Page 6 .  Otherwise.. moving to BULK COLLECT is a smart move! ± Oracle10g will automatically convert CFL to BULK COLLECT in some circumstances! cfl_to_bulk.

± Generally. these are not severe errors. execute: ALTER SESSION SET plsql_warnings = 'enable:06002'.  To use compiler warnings. [ENABLE | DISABLE | ERROR]:[ALL|SEVERE|INFORMATIONAL|PERFORMANCE|warning_number] REM To enable all warnings in your session execute: ALTER SESSION SET plsql_warnings = 'enable:allµ.Page 7 . but potential problems with code structure or performance.Wow! Compile-time warnings!  You can now enable compiler warnings. 'disable:07202'. helping you avoid nuisance issues in your code. you must turn them on in your session. 'enable:performance' . REM If you want to enable warning message number 06002 and all warnings in REM the performance category except warning number 07202. Copyright 2004-2005 Steven Feuerstein .

SQL> CREATE OR REPLACE PROCEDURE dead_code IS 2 x NUMBER := 10. 9 END dead_code. 10 / SP2-0804: Procedure created with compilation warnings SQL> show err Errors for PROCEDURE DEAD_CODE: LINE/COL ERROR -------.example  Check for unreachable code«. 3 BEGIN 4 IF x = 10 THEN 5 x := 20. -.Page 8 .dead code 8 END IF.----------------------------------------------------------------7/7 PLW-06002: Unreachable code plw*. 6 ELSE 7 x := 100.sql Copyright 2004-2005 Steven Feuerstein .Compiler time warnings .

optimization level. Oracle9i introduced ALL_PROCEDURES. Copyright 2004-2005 Steven Feuerstein . etc.  By the way. etc.Page 9 . PIPELINED. which gives you information about the individual programs defined in your schema. DETERMINISTIC.Getting info about program settings  Check the ALL_PLSQL_OBJECT_SETTINGS for information about warnings status. ± AUTHID.

In Oracle10g.FORMAT_ERROR_BACKTRACE Long-standing challenge in PL/SQL: How can I find the line number on which an error was raised in PL/SQL?  Before Oracle10g.DBMS_UTILITY. the only way is to let the error go unhandled in your PL/SQL code!  DBMS_UTILITY. we have "back trace"! Copyright 2004-2005 Steven Feuerstein .Page 10 . ± And is recommended by Oracle in place of SQLERRM.FORMAT_ERROR_STACK only gives you the full error message.

put_line (l_str).Letting the error go unhandled« CREATE OR REPLACE PROCEDURE proc1 BEGIN DBMS_OUTPUT. / CREATE OR REPLACE PROCEDURE proc2 l_str VARCHAR2(30) := 'calling proc1'.put_line ('calling proc2. END.PROC3".sql Copyright 2004-2005 Steven Feuerstein . BEGIN DBMS_OUTPUT.PROC2".Page 11 . END.PROC1". IS IS proc2'). proc1.put_line ('running RAISE NO_DATA_FOUND. END. ERROR at line ORA-01403: no ORA-06512: at ORA-06512: at ORA-06512: at ORA-06512: at 1: data found "SCOTT. / IS proc1'). line 5 line 3 Backtrace. / CREATE OR REPLACE PROCEDURE proc3 BEGIN DBMS_OUTPUT. line 4 "SCOTT. line 8 "SCOTT.

put_line ('calling proc2').sql Copyright 2004-2005 Steven Feuerstein . / SQL> exec proc3 calling proc2 calling proc1 running proc1 ORA-01403: no data found backtrace. EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.Page 12 . END.put_line ( DBMS_UTILITY.FORMAT_ERROR_STACK). proc2.Displaying the ³error stack´ inside PL/SQL CREATE OR REPLACE PROCEDURE proc3 IS BEGIN DBMS_OUTPUT.

Page 13 bt.put_line (DBMS_UTILITY. EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT. proc2. line 5 ORA-06512: at "SCOTT.pkg .PROC3". line 5 Copyright 2004-2005 Steven Feuerstein . END. line 7 ORA-06512: at "SCOTT.Displaying the contents of BACKTRACE CREATE OR REPLACE PROCEDURE proc3 IS BEGIN DBMS_OUTPUT. / SQL> exec proc3 calling proc2 calling proc1 running proc1 Error stack at top level: ORA-06512: at "SCOTT.put_line ('Error stack at top level:').PROC2".FORMAT_ERROR_BACKTRACE).put_line ('calling proc2').PROC1". DBMS_OUTPUT.

ORA-06512: at "SCOTT.show (DBMS_UTILITY.The BACKTRACE stack with re-RAISEs CREATE OR REPLACE PROCEDURE proc1 IS BEGIN SQL> exec proc3 « calling proc2 EXCEPTION calling proc1 WHEN OTHERS THEN running proc1 DBMS_OUTPUT. Program name = PROC1 proc2. ORA-06512: at "SCOTT.END. / Copyright 2004-2005 Steven Feuerstein .put_line (DBMS_UTILITY.put_line ( DBMS_UTILITY. line 11 END. DBMS_OUTPUT.put_line ( 'Error stack in block where raised:').PROC2".format_error_backtrace). Error stack at top level: RAISE.put_line ('Error stack at top level:'). Error stack in block where raised: ORA-06512: at "SCOTT.format_error_backtrace). bt.format_error_backtrace). line 7 / ORA-06512: at "SCOTT.Page 14 . Line number = 11 EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PROC1".PROC3". line 5 DBMS_OUTPUT.put_line ('calling proc2').PROC1". line 5 CREATE OR REPLACE PROCEDURE proc3 IS BEGIN Program owner = SCOTT DBMS_OUTPUT.

PROC1". SQL> exec proc3 / calling proc2 CREATE OR REPLACE PROCEDURE proc2 IS BEGIN DBMS_OUTPUT. line 5 Program owner = SCOTT Program name = PROC2 Line number = 9 .Page 15 calling proc1 running proc1 Error stack in block where raised: ORA-06512: at "SCOTT.put_line (DBMS_UTILITY. proc1.format_error_backtrace).put_line ('running proc1').put_line ('calling proc1').The BACKTRACE stack with new RAISE CREATE OR REPLACE PROCEDURE proc1 IS BEGIN DBMS_OUTPUT. RAISE NO_DATA_FOUND. DBMS_OUTPUT. END. EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT. END. line 9 ORA-06512: at "SCOTT. RAISE.PROC3". line 5 Error stack at top level: ORA-06512: at "SCOTT. / Copyright 2004-2005 Steven Feuerstein . EXCEPTION WHEN OTHERS THEN RAISE VALUE_ERROR.put_line ('Error stack in block where raised:').PROC2".

 Use the INDICES OF clause to use only the row numbers defined in another array. Copyright 2004-2005 Steven Feuerstein . the FORALL driving array no longer needs to be processed sequentially.More flexibility with FORALL  In Oracle10g.  Use the VALUES OF clause to use only the values defined in another array.Page 16 .

l_employees (500) := 7950. BEGIN l_employees (1) := 7839. TYPE boolean_aat IS TABLE OF BOOLEAN INDEX BY PLS_INTEGER. l_employees employee_aat. END. -l_employee_indices (1) := TRUE.Page 17 10g_indices_of.Oracle10g Using INDICES OF DECLARE TYPE employee_aat IS TABLE OF employee. l_employees (100) := 7654.sql .  It only processes the rows with row numbers matching the defined rows of the driving array. l_employee_indices boolean_aat.employee_id%TYPE INDEX BY PLS_INTEGER. l_employee_indices (500) := TRUE. Copyright 2004-2005 Steven Feuerstein . -FORALL l_index IN INDICES OF l_employee_indices UPDATE employee SET salary = 10000 WHERE employee_id = l_employees (l_index).

sql . l_employee_indices (200) := 99999999. l_employee_indices indices_aat.Oracle10g Using VALUES OF DECLARE TYPE employee_aat IS TABLE OF employee. TYPE indices_aat IS TABLE OF PLS_INTEGER INDEX BY PLS_INTEGER.Page 18 10g_values_of. l_employees (99999999) := 7369. l_employees (13067) := 7799. END. -l_employee_indices (100) := -77.  It only processes the rows with row numbers matching the content of a row in the driving array.employee_id%TYPE INDEX BY PLS_INTEGER. -FORALL l_index IN VALUES OF l_employee_indices UPDATE employee SET salary = 10000 WHERE employee_id = l_employees (l_index). BEGIN l_employees (-77) := 7820. l_employees employee_aat. Copyright 2004-2005 Steven Feuerstein .

remove them. Copyright 2004-2005 Steven Feuerstein . etc. INTERSECT and MINUS of two NTs ± Determine if there are duplicates.Nested Tables unveil their MULTISET-edness  Oracle10g introduces high-level set operations on nested tables (only). . This makes set operations of critical importance for manipulating nested tables.Page 19 .  You can now« ± Check for equality and inequality ± Obtain UNION. ± Nested tables are ³multisets.´ meaning that theoretically there is no order to their elements.

ELSE DBMS_OUTPUT. group2 clientele := clientele ('Customer 1'.sql . 'Customer 2'). END IF. group1 clientele := clientele ('Customer 1'. Copyright 2004-2005 Steven Feuerstein . IF group2 != group3 THEN DBMS_OUTPUT. 'Customer 1'). DECLARE TYPE clientele IS TABLE OF VARCHAR2 (64). 'Customer 3').put_line ('Group 1 != Group 2').put_line ('Group 2 = Group 3').put_line ('Group 1 = Group 2').sql 10g_compare_old.Oracle10g Check for equality and inequality  Just use the basic operators«. ELSE DBMS_OUTPUT. group3 clientele := clientele ('Customer 3'.Page 20 10g_compare. END IF. END. BEGIN IF group1 = group2 THEN DBMS_OUTPUT.put_line ('Group 2 != Group 3').

our_favorites). our_favorites := dad_favorites MULTISET UNION my_favorites.Oracle10g UNION. show_favorites ('MINE then DAD with DISTINCT'. show_favorites ('IN COMMON'.sql 10g_string_nt. INTERSECT.sql Copyright 2004-2005 Steven Feuerstein . our_favorites).sql 10g*union*.sql 10g_favorites. END. MINUS  Straightforward. show_favorites ('ONLY DAD''S'. with the MULTISET keyword. show_favorites ('MINE then DAD'. show_favorites ('DAD then MINE'. our_favorites). 10g_setops. our_favorites := my_favorites MULTISET UNION DISTINCT dad_favorites.Page 21 . our_favorites := dad_favorites MULTISET EXCEPT my_favorites. our_favorites := my_favorites MULTISET INTERSECT dad_favorites. BEGIN our_favorites := my_favorites MULTISET UNION dad_favorites. our_favorites). our_favorites).

p.l (keep_it_simple IS NOT A SET. p.l (keep_it_simple IS A SET. END.pkg Copyright 2004-2005 Steven Feuerstein . p.l (favorites_pkg. 'My favorites distinct?'). p.Oracle10g Distinct sets of values  Use the SET operator to work with distinct values. 'Keep_it_simple NOT distinct?'). 'Keep_it_simple distinct?'). BEGIN keep_it_simple := SET (favorites_pkg.show_favorites ( 'DISTINCT SET'. favorites_pkg.show_favorites ('FULL SET'. 'My favorites NOT distinct?').sql 10g_favorites.my_favorites IS NOT A SET.my_favorites).my_favorites IS A SET.l (favorites_pkg. keep_it_simple). 10g_set.Page 22 . and determine if you have a set of distinct values.my_favorites). DECLARE keep_it_simple strings_nt := strings_nt (). favorites_pkg. favorites_pkg.

my_favorites .eli_favorites NOT SUBMULTISET OF favorites_pkg.sql 10g_favorites. BEGIN p. 'Father follows son?').my_favorites SUBMULTISET OF favorites_pkg.l (favorites_pkg.my_favorites .pkg . 'Father doesn''t follow son?'). 'Son follows father?').l (favorites_pkg.Oracle10g Determining subsets of data  Use the SUBMULTISET operator to determine if a nested table contains only elements that are in another nested table. Copyright 2004-2005 Steven Feuerstein .eli_favorites . 'Son doesn''t follow father?').eli_favorites .Page 23 10g_submultiset.eli_favorites SUBMULTISET OF favorites_pkg.l (favorites_pkg.my_favorites NOT SUBMULTISET OF favorites_pkg. p. p.l (favorites_pkg. p. END.

Oracle10g Various Oracle10g improvements  Alternative quoting mechanism  Integer and floating point data type improvements  Compiler time warnings (hurray!)  Optimizing compiler (who would have thought!)  Regular expression support Copyright 2004-2005 Steven Feuerstein .Page 24 .

Literal using old quoting mechanism 'TZ=''CDT6CST''' '''' 'It''s here' '''''' Copyright 2004-2005 Literal using new quoting mechanism q'(TZ='CDT6CST')' q'-'-' q'[It's here]' nq'^''^' Actual Value TZ='CDT6CST' ' It's here '' 10g_quotes.sql Steven Feuerstein . you could sometimes tear your hair out.Page 25 .Oracle10g Alternative quoting mechanism  What do you do when you need to put a single quote inside a literal string? ± Before Oracle10g. ± Now just specify an alternative quote character.

only PLS_INTEGER was so blessed. for all 32-bit INTEGER types (BINARY_INTEGER and its subtypes) ± Previously.Page 26 . and the double precision BINARY_DOUBLE.  Support for IEEE 754 compliant floating point numbers to both SQL and PLSQL: single precision BINARY_FLOAT. So now you can use whichever type you want and not feel concerned about a performance hit.Oracle10g Integer and floating point data type improvements  Oracle now uses ³machine arithmetic.´ rather than C library arithmetic. ± Faster and better for scientific number crunching. Copyright 2004-2005 Steven Feuerstein .

Oracle10g Regular expression support  Oracle10g supports the use of regular expressions via four new built-in functions: REGEXP_LIKE.´  Various examples on the next page. REGEXP_INSTR.Page 27 . and REGEXP_REPLACE. through the use of ³meta-characters. REGEXP_SUBSTR. ± Available in both SQL and PL/SQL ± Gives you much more flexibility and power in processing text. Copyright 2004-2005 Steven Feuerstein .

by replacing -.Begins with 212. optionally enclosed by parentheses APPLY_NYC_SURCHARGE. -.com'.Page 28 .com')). END IF.*\. '[[:digit:]]+[:space:]').change the domain part of the email addresses.'^\(?212\)?' THEN -.Oracle10g Regular expression examples IF REGEXP_LIKE(phone_number. Copyright 2004-2005 Steven Feuerstein .(up to a whitespace character) street_number := REGEXP_SUBSTR(address_line1. -. '@.PUT_LINE ( REGEXP_REPLACE(email_address.'@new_domain.com' with new domain name DBMS_OUTPUT.get the leading number part of the address -.everything between the @ and the '.

the main thing is to grow your awareness of what is possible.Page 29 . Copyright 2004-2005 Steven Feuerstein . but the most important stuff (optimizing. mostly transparent  Oracle10g offers some major new functionality. compiler warnings) are transparent. enhancements will naturally fill in gaps of functionality that respond to more specialized interests.Really nice stuff. ± Just upgrade and start having fun!  As PL/SQL matures. ± Don't worry if you don't see a need for features like INDICES OF right now.