You are on page 1of 148

Oracle PL/SQL Programming

Anti-Pattern
PL/SQL
Programming

Steven Feuerstein
steven@stevenfeuerstein.com
www.StevenFeuerstein.com
www.PLSQLChallenge.com

Copyright 2013 - Feuerstein and Associates, all rights reserved

Oracle PL/SQL Programming

What's an Anti-Pattern?
• Design Patterns in software recognizes reality:
most of the code we write follows a pattern.
– Different entities, same logic.

• Define the pattern - and the patterned
solution - and we can code more productively
and confidently.
• Anti-patterns are negative patterns.
– Common but wrong ways to write code.

• And a great learning device!
Copyright 2013 Feuerstein and Associates

Page 2

Oracle PL/SQL Programming

How the Anti-Pattern Class Works
• I present on an area of PL/SQL functionality.
– You listen and sort-of learn. :-)

• Then I let you loose on some anti-patterns.
– Start with bad code, rewrite it to good code.

• We will use the PL/SQL Challenge (plsqlchallenge.com).
– You have an account set up for your email address,
password same as email.
– Log in and find the Anti-Pattern "quizzes" in the Play a Quiz
table.
– Pick the appropriate quiz and then follow the directions.

• Most important: execute the setup code.

Copyright 2013 Feuerstein and Associates

Page 3

Oracle PL/SQL Programming Anti-Pattern PL/SQL Agenda • • • • • PL/SQL fundamentals Error raising and handling Working with collections Writing and running SQL in PL/SQL Key maintainability techniques Copyright 2013 Feuerstein and Associates Page 4 .

ToadWorld.com/SF  Download and use any of my scripts (examples. performance scripts. ask questions.sql  You have my permission to use all these materials to do internal trainings and build your own applications. focus on concepts and principles. – You must test them and modify them to fit your needs. filename_from_demo_zip.Oracle PL/SQL Programming How to benefit most from this training • Watch. – But remember: they are not production ready. reusable code) from the same location: the demo. listen. • Download and use any of my training materials: PL/SQL Obsession http://www. Copyright 2013 Feuerstein and Associates Page 5 .zip file.

Oracle PL/SQL Programming Websites for PL/SQL Developers www.plsqlchallenge.com 27+ hours of detailed video training on Oracle PL/SQL www.stevenfeuerstein.plsqlchannel.com Daily PL/SQL quiz with weekly and monthly prizes www.com Monthly PL/SQL newsletter Copyright 2013 Feuerstein and Associates Page 6 .

Oracle PL/SQL Programming PL/SQL Fundamentals • Compiler optimization • Context switching in Oracle • Memory management Copyright 2013 Feuerstein and Associates Page 7 .

– Compile time increases. – The compiler rearranges your code. runtime performance improves. less impact on compile times – 2 Most aggressive. biggest impact on compile time. • You choose the level of optimization : – 0 Pre-10g compilation without optimization – 1 Smaller scale change. Copyright 2013 Feuerstein and Associates Page 8 . [default] – 3 (Oracle11g) In-lining of local subprograms. in addition to all the optimization performed at level 2 • Stick with the default. unless you have a clear need for an exception.Oracle PL/SQL Programming The Optimizing Compiler • The PL/SQL compiler now has the ability to automatically optimize your code. maximum possible code transformations.

– In essence. for example. • Optimization does not change the logical behavior of your code. changing the route that the runtime engine takes to get from point A to point B in your code. – The actual arguments of a call or a SQL statement may be evaluated in any order (including default actual arguments). – Operands of a commutative operator may be commuted.Oracle PL/SQL Programming The PL/SQL Optimizer: High Level View • The optimizer takes advantage of "freedoms" to reorder the execution of statements. • Some examples: – Unless otherwise specified. – Optimization should not. the operands of an expression operator may be evaluated in any order.sql Page 9 . cause any of your regression tests to suddenly fail! Copyright 2013 Feuerstein and Associates 10g_optimize_cfl.

it is composed of many individual processes and memory areas. so what happens then? – Oracle switches the context. but it is not one big thing . – PL/SQL statements are executed by the PL/SQL statement engine.Oracle PL/SQL Programming Context Switching in Oracle • We talk about the "backend". Copyright 2013 Feuerstein and Associates Page 10 . • But PL/SQL calls SQL and SQL calls PL/SQL. – SQL statements are executed by the SQL statement engine.

employee_id. END LOOP. Oracle Database PL/SQL Runtime Engine PL/SQL block FOR rec IN emp_cur LOOP UPDATE employee SET salary = .Oracle PL/SQL Programming When PL/SQL Calls SQL…... WHERE employee_id = rec. Procedural statement executor SQL Engine SQL statement executor Performance penalty for many “context switches” Copyright 2013 Feuerstein and Associates Page 11 .

END.Oracle PL/SQL Programming And It Goes Both Ways • A query can call a PL/SQL function. RETURN l_return. / IN VARCHAR2. CREATE OR REPLACE FUNCTION full_name (first_in last_in RETURN VARCHAR2 IS BEGIN RETURN first_in || ' ' || last_in. IN VARCHAR2) CREATE OR REPLACE FUNCTION emp_name (employee_id_in IN INTEGER) RETURN VARCHAR2 IS l_return VARCHAR2 (32767). END. last_name) INTO l_return FROM employees. / SELECT emp_name (employee_id) FROM employees / Copyright 2013 Feuerstein and Associates Page 12 . which contains a SELECT that calls a function…. BEGIN SELECT full_name (first_name.

Oracle PL/SQL Programming Watch out for those Context Switches! • We will explore a number of techniques for reducing the number and/or cost of context switches in the class.our first exercise! Copyright 2013 Feuerstein and Associates Page 13 . – Watch out for flipping back and forth between SQL and PL/SQL! • And now…. • But the responsibility falls on you to make sure that your code makes sense.

Oracle PL/SQL Programming Anti-Pattern PL/SQL Exercise Time! PL/SQL Challenge .Play a Quiz Anti-Pattern PL/SQL Context Switching Copyright 2013 Feuerstein and Associates Page 14 .

like collections and FORALL. in fact.Oracle PL/SQL Programming Memory Management and PL/SQL Code • It is certainly possible to write PL/SQL code that consumes so much memory.sql Page 15 . • As you work with more advanced features. and make adjustments. you will need to pay attention to memory. it kills a user's session. Copyright 2013 Feuerstein and Associates memory_error. • Let's review how Oracle manages memory at run-time. – It's quite easy to do.

emp_rec emp%rowtype. tot_tab tottabtype.. tot_tab tottabtype.. upd_salaries emp_rec emp%rowtype. Session 1 memory (PGA/UGA) Session 2 memory (PGA/UGA) Copyright 2013 Feuerstein and Associates Session 2 Page 16 .Oracle PL/SQL Programming PL/SQL in Shared Memory System Global Area (SGA) of RDBMS Instance Shared Pool Reserved Pool Library cache Shared SQL Select * from emp Pre-parsed Large Pool Session 1 calc_totals show_emps Update emp Set sal=.

– In PL/SQL.Nextval. END Pkg. • The User Global Area contains session-specific data that persists across server call boundaries – Package-level data • The Process Global Area contains session-specific data that is released when the current server call terminates: "local" data. this is limited to package static constants.Oracle PL/SQL Programming How PL/SQL uses the SGA. PGA and UGA PACKAGE Pkg is /* 11g feature! */ Nonstatic_Constant CONSTANT PLS_INTEGER := My_Sequence. Copyright 2013 Feuerstein and Associates Page 17 . • The SGA contains information that can be shared across sessions connected to the instance. Static_Constant CONSTANT PLS_INTEGER := 42.

v_$sesstat s. 'session pga memory') • Oracle keeps track of and shows the PGA and UGA consumption for a session in the v_$sesstat dynamic view. PL/SQL developers can analysis their code's memory usage.sql Page 18 . Copyright 2013 Feuerstein and Associates show_pga_uga.statistic# = n. plsql_memory.Oracle PL/SQL Programming Calculating PGA and UGA Consumption SELECT n.sql plsql_memory.sid = my_session.statistic# AND s.v_$statname n WHERE s. s. • With the correct privileges.sql grantv$. END.show_memory_usage.start_analysis.pkg plsql_memory_demo.name IN ('session uga memory'. run_my_application. BEGIN plsql_memory. sys.VALUE FROM sys.sid AND n.name.

" • Use NOCOPY hint when passing IN OUT collections.tst tabfunc_pipelined.sql varray_collection_limit. • Be very careful about defining variables at the package level.sql Page 19 . • Use pipelined table functions. • Use varrays with BULK COLLECT to declaratively guard against "memory creep.sql nocopy*. – Memory will not be released when the block terminates. Copyright 2013 Feuerstein and Associates bulklimit.Oracle PL/SQL Programming Tips for managing memory • Use LIMIT clause with BULK COLLECT.

Oracle PL/SQL Programming Error Management in PL/SQL • Things go wrong . – Provide key information to users and record diagnostic info for us to use to resolve problem.all the time. • Do that effectively. – Exception handling architecture – Built-in functions Copyright 2013 Feuerstein and Associates Page 20 . we need to leverage all the features Oracle has to offer. • We need to anticipate problems and handle problems.

– With PRAGMA EXCEPTION_INIT.Oracle PL/SQL Programming Raising Exceptions • Oracle raises exceptions.and handle it by name. • You can raise exceptions as well. – Use RAISE_APPLICATION_ERROR to pass an application-specific message back to a user. Copyright 2013 Feuerstein and Associates raise. – Use RAISE to raise an exception.sql Page 21 .sql raise_application_error. • You can also define your own exceptions so that you can raise that exception .

Copyright 2013 Feuerstein and Associates info_for_handling. – Exceptions raised in declaration section are not handled.traps almost any exception.sql excquiz*.traps one exception – WHEN exc1 OR exc2 . • The EXCEPTION section contains one or more WHEN clauses.sql Page 22 .Oracle PL/SQL Programming Handling Exceptions • After exception is raised. – WHEN exc .traps more than one – WHEN OTHERS . the block closes and control is passed to the exception section or propagates unhandled to an outer block.

Oracle PL/SQL Programming

Impact of errors on DML execution
• A single DML statement can result in changes to
multiple rows.
• When an error occurs on a change to a row....
– All previous changes from that statement are rolled
back.
– No other rows are processed.
– An error is passed out to the calling block (turns into a
PL/SQL exception).
– No rollback on completed DML in that session.

• Usually acceptable, but what if you want to:
– Avoid losing all prior changes?
– One way to do this with SAVE EXCEPTIONS
Copyright 2013 Feuerstein and Associates

errors_and_dml.sql
continue_past_exceptions.sql

Page 23

Oracle PL/SQL Programming

Anti-Pattern Exercise Time!

PL/SQL Challenge - Play a Quiz
Anti-Pattern PL/SQL Error Management Basics

Copyright 2013 Feuerstein and Associates

Page 24

Oracle PL/SQL Programming

Oracle Built-ins For Handling Exceptions
• In addition to the application-specific
information you may want to log, Oracle builtins provide you with answers to the following
questions:
– How did I get here?
– What is the error code?
– What is the error message and/or stack?
– On what line was the error raised?

Copyright 2013 Feuerstein and Associates

Page 25

sql sqlcode_test.Oracle PL/SQL Programming SQLCODE and SQLERRM • SQLCODE returns the error code of the most recently-raised exception in your session. • SQLERRM returns the error message associated with SQLCODE – but it also a generic error message lookup function. – You must assign them to local variables to use their values in SQL statements (like writing to an error log).sql Copyright 2013 Feuerstein and Associates Page 26 . sqlcode. • Neither SQLCODE nor SQLERRM can be called from within a SQL statement.

sqlerrm. – When called outside of an exception handler. – Oracle recommends you use DBMS_UTILITY.FORMAT_ERROR_STACK instead. it returns the error message for the SQLCODE value.Oracle PL/SQL Programming SQLERRM Details • If you don't pass an argument to SQLERRM. – When there is a stack of errors. • The maximum size of a string returned by SQLERRM is 512 bytes.sql Copyright 2013 Feuerstein and Associates Page 27 . • You can also pass an error code to SQLERRM and it will return the generic error message. Oracle may truncate the string returned by SQLERRM. always returns "success" message – no error.

Copyright 2013 Feuerstein and Associates Page 28 .Oracle PL/SQL Programming DBMS_UTILITY error functions • Answer the question "How did I get here?" with DBMS_UTILITY. • Get a more complete error message with DBMS_UTILITY.FORMAT_CALL_STACK. • Find line number on which error was raised with DBMS_UTILITY.FORMAT_ERROR_BACKTRACE.FORMAT_ERROR_STACK.

FORMAT_CALL_STACK • The "call stack" reveals the path taken through your application code to get to that point. callstack. • Very useful whenever tracing or logging errors.sql callstack. • The string is formatted to show line number and program unit name.pkg Copyright 2013 Feuerstein and Associates Page 29 . – But it does not reveal the names of subprograms in packages.Oracle PL/SQL Programming DBMS_UTILITY.

• Oracle recommends you use this instead of SQLERRM.sql Copyright 2013 Feuerstein and Associates Page 30 . to reduce the chance of truncation.Oracle PL/SQL Programming DBMS_UTILITY. • Returns a string of maximum size 2000 bytes (according to the documentation). errorstack.FORMAT_ERROR_STACK • This built-in returns the error stack in the current session. – Possibly more than one error in stack.sql big_error_stack. • Returns NULL when there is no error.

2) answers the question: "Where was my error raised? – Prior to 10.Oracle PL/SQL Programming DBMS_UTILITY. call BACKTRACE and store that information to avoid losing the original line number. • When you re-raise your exception (RAISE. – So before a re-raise. backtrace.pkg Copyright 2013 Feuerstein and Associates Page 31 .sql bt. • Call it whenever you are logging an error.2. you could not get this information from within PL/SQL. subsequent BACKTRACE calls will point to that line.FORMAT_ERROR_BACKTRACE • The backtrace function (new to 10.) or raise a different exception.

you could obtain several kinds of "stacks" through individual function calls: – DBMS_UTILITY. 12c_utl_callstack*.FORMAT_ERROR_BACKTRACE .FORMAT_CALL_STACK .1) • Prior to 12c."On what line was my error raised?" • Now."What is the error message/stack?" – DBMS_UTILITY.Oracle PL/SQL Programming The UTL_CALL_STACK Package (12.FORMAT_ERROR_STACK . the UTL_CALL_STACK package supports all that and a much better API to the info in the stack.sql Copyright 2013 Feuerstein and Associates Page 32 ."How did I get here?" – DBMS_UTILITY.

Oracle PL/SQL Programming Anti-Pattern Exercise Time! PL/SQL Challenge .Play a Quiz Anti-Pattern PL/SQL Error Management Built-Ins Copyright 2013 Feuerstein and Associates Page 33 .

• Use them to maintain in-program (PGA) lists…very fast! • Collections enable other key features of PL/SQL 1 Apple 22 Pear 100 Orange 10023 Apricot – BULK COLLECT and FORALL use them to boost multi-row SQL performance – Serve up complex datasets of information to non-PL/SQL host environments using table functions. similar to 3GL arrays. Copyright 2013 Feuerstein and Associates Page 34 .Oracle PL/SQL Programming Working with PL/SQL Collections • Collections are single-dimensioned lists of information.

sql varray_example.sql Copyright 2013 Feuerstein and Associates Page 35 .sql nested_table_example.PL/SQL only datatype – Nested table and varray (varying arrays) .Oracle PL/SQL Programming Different Types of Collections • Three types of collections – Associative array .used in PL/SQL and SQL • Use collection methods to navigate through and manipulate collections. • Watch out for PGA consumption! assoc_array_example.

to the name of the type/class or to an instance of the class. number of elements allowed in a VARRAY. • DELETE deletes one or more rows from an associative array or nested table. • NEXT/PRIOR: defined index value after/before the specified index value . • FIRST/LAST: lowest/highest index values of defined rows. • EXTEND adds rows to the end of a nested table or varray. • COUNT: number of elements defined in collection.sql plsqlloops.Oracle PL/SQL Programming Methods that retrieve information • You invoke a method by attaching it.sp collection_exists. using dot notation. • EXISTS: TRUE if the specified index values is defined. Copyright 2013 Feuerstein and Associates method_vs_proc.sql varray_limit.sql extend. • TRIM removes rows from a varray or nested table.sql Page 36 .sql delete. • LIMIT: max.

Oracle PL/SQL Programming Anti-Pattern Exercise Time! PL/SQL Challenge .Play a Quiz Anti-Pattern PL/SQL Collection Methods Copyright 2013 Feuerstein and Associates Page 37 .

– You can index by integer or strings. collection_of_records.* Copyright 2013 Feuerstein and Associates Page 38 . – The order added is significant. • But how do you find an element in the list? What if the element is a record and you need to find elements by different fields? • Associative arrays can help because…. – An associative array can be sparse.sql string_tracker0.Oracle PL/SQL Programming Creative Uses of Associative Array Indexes • Sometimes you add items to end of list.

collection_of_records. • Combine these two features and you have a powerful and relatively simple mechanism for emulating relational table keys. – Very often primary keys of tables are sequencegenerated integers that fall within this range. – Certainly.Oracle PL/SQL Programming Taking advantage of non-sequential indexing • Associative arrays can be sparse. • Valid index values for an associative array cover a very wide range of integers. any string-indexed collection is not sequentially filled.sql Copyright 2013 Feuerstein and Associates Page 39 .

but it is rarely the case.sql emulate_primary_key2. emulate_primary_key1.sql Copyright 2013 Feuerstein and Associates Page 40 . • These scenarios mesh perfectly with the features of an integer-indexed associative array. • Primary keys generally are not "densely" allocated. – Sequences are allocated in groups. – It is possible that this sequence value could exceed 2**31-1. rows are deleted.Oracle PL/SQL Programming Emulating Primary Key in Collection • Many tables rely on sequence-generated integer values for their primary keys.

• What if I need to do the same thing in a collection? • You can only have a single index on an associative array (INDEX BY.sql genaa. – But you could create other collections that serve as indexes into the "original" collection.. emulate_indexes..sql Copyright 2013 Feuerstein and Associates Page 41 .).Oracle PL/SQL Programming "Multiple Indexes" on a Collection • Most relational tables have multiple indexes defined in order to optimize query performance (for various WHERE clauses).

LAST. but they are not necessary and they lead to code bloat. the higher the overhead to "hash" or convert that string to the integer that is actually used as the index value.they're fast.sql assoc_array_perf. looking for a match on a value. • Good to keep in mind: – FIRST.tst string_tracker2. – The longer the string values.Oracle PL/SQL Programming Working with string-indexed collections • The anti-pattern: code that iterates through a collection. Copyright 2013 Feuerstein and Associates assoc_array*. NEXT and PRIOR methods return strings.* Page 42 . – A "full collection scan" .

Oracle PL/SQL Programming Anti-Pattern Exercise Time! PL/SQL Challenge .Play a Quiz Anti-Pattern PL/SQL Creative Indexing with Arrays Copyright 2013 Feuerstein and Associates Page 43 .

nested_collections. • The syntax for working with multilevel collections can be hard to parse (in your head). – Field in record.Oracle PL/SQL Programming Nested Collections • The element of a nested collection type is itself a collection or contains a collection.sql Copyright 2013 Feuerstein and Associates Page 44 . attribute in object type • Usages for multilevel collections: – Model normalized data structures in PL/SQL collections – Emulate multidimensional arrays.

The hard way: segmenting one big collection List 1: 1-10000 Copyright 2013 Feuerstein and Associates List 2: 10001-20000 List 2: 20001-30000 string_tracker3*. Ugh. • But what if we now need to keep track of items in more than one list? • A "list of lists" does the job very nicely! – Or you could go "hard code" and "old school" by segmenting one big collection.Oracle PL/SQL Programming String Tracker Version 3 • We've already enhanced the String Tracker package to avoid a full collection scan.* Page 45 .

Oracle PL/SQL Programming Anti-Pattern Exercise Time! PL/SQL Challenge .Play a Quiz Anti-Pattern PL/SQL Nested Collections Copyright 2013 Feuerstein and Associates Page 46 .

– Perhaps nested collections can come to the rescue! Copyright 2013 Feuerstein and Associates Page 47 ." take a look at how you are using your collections (or SQL). and greatly simplify your algorithms.Oracle PL/SQL Programming Conclusions – Nested Collections • The nested collection is a powerful. feature of PL/SQL. • If you find yourself saying "It shouldn't be this hard. • Used correctly. it can hide complexity in the underlying data structure. but potentially very complicated.

"multisets. Oracle added MULTISET set operators to manipulate the contents of nested tables (only). from a theoretical standpoint. – Use in both PL/SQL blocks and SQL statements. • In Oracle Database 10g.Oracle PL/SQL Programming Manipulating Nested Tables as Multisets • Nested tables are. – Relational tables are multisets as well. so it must be manipulated as a set. • If a set has no order. Copyright 2013 Feuerstein and Associates Page 48 . – Duplicates are allowed and are significant. then it has no index." – There is no inherent order to the elements.

– – – – two nested tables are equal/unequal a nested table has duplicates.. not MINUS). – Return common elements of two nested tables with MULTISET INTERSECT.Oracle PL/SQL Programming Set-Oriented Features for Nested Tables • Determine if. – Take away the elements of one nested table from another with MULTISET EXCEPT (oddly. and remove duplicates one nested table contains another an element is a member of a nested table • Perform set operations.. – Join contents of two nested tables: MULTISET UNION. Copyright 2013 Feuerstein and Associates Page 49 .

BEGIN IF group1 = group2 THEN DBMS_OUTPUT. END IF. group2 clientele := clientele ('Customer 1'. 'Customer 2').sql Copyright 2000-2008 Steven Feuerstein .put_line ('Group 1 = Group 2'). ELSE DBMS_OUTPUT. DECLARE TYPE clientele IS TABLE OF VARCHAR2 (64).sql 10g_compare_nulls. 10g_compare. 'Customer 3'). – But watch out! NULLs have the usual disruptive impact. 'Customer 1').Page 50 10g_compare_old. END. group3 clientele := clientele ('Customer 3'. • This is an enormous advantage over writing a program to compare the contents of two collections.sql Copyright 2013 Feuerstein and Associates Page 50 .put_line ('Group 1 != Group 2').Oracle PL/SQL Programming Check for equality and inequality • You can use = and <> to compare the contents of two nested tables. group1 clientele := clientele ('Customer 1'.

Copyright 2000-2008 Steven Feuerstein .my_favorites IS A SET.my_favorites). BEGIN keep_it_simple := SET (favorites_pkg.sql Page 51 .my_favorites).l (keep_it_simple IS NOT A SET.l (favorites_pkg. END.Page 51 Copyright 2013 Feuerstein and Associates authors. p.pkg 10g_set. favorites_pkg.show_favorites ('FULL SET'. 'Keep_it_simple NOT distinct?'). keep_it_simple).Oracle PL/SQL Programming Nested table duplicates – detection and removal • Use the SET operator to work with distinct values. DECLARE keep_it_simple strings_nt := strings_nt ().my_favorites IS NOT A SET. 'My favorites distinct?'). p.show_favorites ( 'DISTINCT SET'.l (favorites_pkg. and determine if you have a set of distinct values. favorites_pkg. p.l (keep_it_simple IS A SET. favorites_pkg. 'My favorites NOT distinct?'). 'Keep_it_simple distinct?'). p.

you cannot compare individual fields of records. • Performance in PL/SQL is fast. • The implementation in SQL itself is quite slow.sql Page 52 . – Performs an equality check for the entire element.* 10g_member_of.Oracle PL/SQL Programming Determine if value is in nested table • Use the MEMBER OF syntax to determine if a value is in the nested table. – Much simpler than scanning the contents of a collection. and so on. Copyright 2013 Feuerstein and Associates in_clause.

END IF.Oracle PL/SQL Programming Does one nested table contains another? • The SUBMULTISET OF operator determines if all the elements of one nested table are in another. nt1 nested_typ := nested_typ (1. DECLARE TYPE nested_typ IS TABLE OF NUMBER. 1). nt2 nested_typ := nested_typ (3.pkg 10g_submultiset. 2). END. / Copyright 2013 Feuerstein and Associates authors.sql Page 53 . 2.. BEGIN IF nt1 SUBMULTISET OF nt2 THEN ..

– You do not need to initialize or extend first.sql Page 54 . • Duplicates are preserved unless you include the DISTINCT modifier. – This is the opposite of SQL UNION and UNION ALL.Oracle PL/SQL Programming UNION two nested tables together • Use UNION to join together the contents of two nested tables. Copyright 2013 Feuerstein and Associates authors. • The resulting collection is either empty or sequentially filled from index value 1.pkg 10g_union.

Oracle PL/SQL Programming Intersect two nested tables together • Use INTERSECT to find the common elements of two nested tables. – And the ALL modifier is the default. Copyright 2013 Feuerstein and Associates 10g_intersect.sql Page 55 . – You do not need to initialize or extend first. • The resulting collection is either empty or sequentially filled from index value 1. • Duplicates are preserved unless you include the DISTINCT modifier.

– You do not need to initialize or extend first. • The resulting collection is either empty or sequentially filled from index value 1.Oracle PL/SQL Programming Take away the elements of one nested table from another • Use EXCEPT (not MINUS!) to take all elements in one nested table out of another.sql Page 56 . – And the ALL modifier is the default. • Duplicates are preserved unless you include the DISTINCT modifier. Copyright 2013 Feuerstein and Associates 10g_except.

Oracle PL/SQL Programming Anti-Pattern Exercise Time! PL/SQL Challenge .Play a Quiz Anti-Pattern PL/SQL Nested Table Features Copyright 2013 Feuerstein and Associates Page 57 .

Oracle PL/SQL Programming Conclusions – MULTISET operators • When you need to manipulate the contents of a collection as a set. SUBMULTISET and MEMBER operators also can come in very handy. • The SET. Copyright 2013 Feuerstein and Associates Page 58 . • Watch out for results when your nested table may contain NULL elements. use a nested table. simple way to avoid writing lots of code. • The MULTISET operators offer a powerful.

. – Work within PL/SQL code only – Sparsely fill and manipulate the collection – Take advantage of negative index values or string indexing • Use nested tables when you need to. – Access the collection inside SQL (table functions. – If you need to specify a maximum size to your collection – Optimize performance of storing collection as column Copyright 2013 Feuerstein and Associates Page 59 .... columns in tables..Oracle PL/SQL Programming Choosing the best type of collection • Use associative arrays when you need to.. or utilize SQL operations) – Want or need to perform high level set operations (MULTISET) • Use varrays when you need to.

com/SF Copyright 2013 Feuerstein and Associates Page 60 .ToadWorld. Hands-On Collection seminar www. high quality PL/SQL code. unless you use collections. • Learn collections thoroughly and apply them throughout your backend code. collections are required.Oracle PL/SQL Programming Collections: Don't start coding without them. taking full advantage of new features. – From array processing to table functions. • It is impossible to write efficient. – Your code will get faster and in many cases much simpler than it might have been (though not always!).

Oracle PL/SQL Programming SQL in PL/SQL • SQL: the heart and soul of any Oracle-based application. ugly mess • We'll start with some principles • Move on to key features for executing SQL inside PL/SQL program units. Copyright 2013 Feuerstein and Associates Page 61 . • PLSQL: the best place to put your SQL – And the opportunity to create a slow. – And also the problem child.

– Multiple places in code – Multiple executions of same statement – Multiple retrievals of same (unchanged) data Copyright 2013 Feuerstein and Associates Page 62 . • Avoid repetition of the same SQL statement. – It is almost always going to be more efficient and easier to maintain than an implementation in PL/SQL.Oracle PL/SQL Programming Principles for Writing SQL in PL/SQL • Do as much as you can in SQL.

– I am a good example of what you don't want to do or how to be. • If you don't keep up with SQL capabilities. more complicated PL/SQL code than is necessary. Copyright 2013 Feuerstein and Associates Page 63 . • So take the time to refresh your understanding of Oracle SQL in 10g and 11g. you will write slower.Oracle PL/SQL Programming Fully leverage SQL in your PL/SQL code • Oracle continually adds significant new functionality to the SQL language.

Oracle PL/SQL Programming Some exciting recently added SQL features • Courtesy of Lucas Jellema of AMIS Consulting • Analytical Functions – Especially LAG and LEAD.deptno . etc. • WITH clause (subquery factoring) – Allows the definition of 'views' inside a query that can be used and reused. these allow you to look to previous and following rows to calculate differences.deptno = d. • ANSI JOIN syntax – Replaces the (+) operator and introduces FULL OUTER JOIN • SYS_CONNECT_BY_PATH and CONNECT_BY_ROOT for hierarchical queries • Scalar subquery – Adds a subquery to a query like a function call. (select count(*) from emp e where e.deptno) number_staff from dept Page 64 . Copyright 2013 Feuerstein and Associates select d. they allow procedural top-down logic inside a query • Flashback query – No more need for journal tables. history tables.

last_name LIKE '%s%' THEN DBMS_OUTPUT. less in your PL/SQL code. END IF. END LOOP.last_name). Copyright 2013 Feuerstein and Associates Page 65 . – Below a very simple demonstration of the principle – Move the IF statement into the WHERE clause of the query! BEGIN FOR employee_r IN ( SELECT last_name FROM employees ORDER BY employee_id) LOOP IF employee_r. END.Oracle PL/SQL Programming "Load up" Your SQL • Put as much application logic into your SQL statements.put_line (employee_r.

Oracle PL/SQL Programming Anti-Pattern Exercise Time! PL/SQL Challenge .Play a Quiz Anti-Pattern PL/SQL Maximize SQL Copyright 2013 Feuerstein and Associates Page 66 .

• Multiple retrievals of same (unchanged) data – Use caching features. "switch" to bulk processing. especially the function result cache. worse to repeat the same SQL statement • Multiple executions of same statement – Unnecessary context switches.Oracle PL/SQL Programming Avoid Repetition of the Same SQL • Multiple places in code – Bad to repeat hard-coded literals. Copyright 2013 Feuerstein and Associates Page 67 .

* l_manager employees employee_id = l_employee. again! */ SELECT INTO FROM WHERE END. CREATE OR REPLACE PROCEDURE do_stuff_with_employee ( employee_id_in IN employees.Oracle PL/SQL Programming Multiple Places in Code • It's so easy to write SQL in PL/SQL that we take it for granted. and then. BEGIN SELECT * INTO l_employee FROM employees WHERE employee_id = employee_id_in. especially the "simple" and "never changing" statements like….manager_id. l_manager employees%ROWTYPE..employee_id%TYPE) IS l_employee employees%ROWTYPE. Copyright 2013 Feuerstein and Associates Page 68 .. /* Do some stuff.

• Solution: use a data access layer that isolates SQL behind named objects. your application will be extremely difficult to maintain. procedures and functions. Copyright 2013 Feuerstein and Associates Page 69 .Oracle PL/SQL Programming Repetition of SQL -> Maint. • Then call the program unit or execute a query against the view. where and how to write SQL. including views. Nightmare • If you do not put guidelines in place for when.

Oracle PL/SQL Programming Anti-Pattern Exercise Time! PL/SQL Challenge .Play a Quiz Anti-Pattern PL/SQL Same SQL Multiple Places Copyright 2013 Feuerstein and Associates Page 70 .

Copyright 2013 Feuerstein and Associates Page 71 . • This row-by-row processing results in many context switches and corresponding performance degradation.inside a loop (usually a cursor FOR loop). • This means that the same statement is executed. • Solution: switch to bulk processing (BULK COLLECT and FORALL).Oracle PL/SQL Programming Multiple Executions of Same Statement • Your SQL may only exist in one place . with only changes in bind variables.

static and dynamic. explicit. – Move data from tables into collections. – Use with inserts. deletes and merges. – Move data from collections to tables.Oracle PL/SQL Programming Bulk Processing in PL/SQL • The goal is straightforward: reduce the number of context switches and you improve performance. updates. • BULK COLLECT speeds up queries. – Can be used with all kinds of queries: implicit. • To do this. • FORALL speeds up DML. Copyright 2013 Feuerstein and Associates Page 72 . Oracle "bundles up" the requests for data (or to change data) and then passes them with a single context switch.

LAST UPDATE employee SET salary = . same SQL behavior SQL Engine SQL statement executor Update. list_of_emps. Update.... Update.FIRST.. Update. Update........Oracle PL/SQL Programming Bulk processing with FORALL Oracle server PL/SQL Runtime Engine PL/SQL block FORALL indx IN list_of_emps.. Update....... Update.. Update. Update.. WHERE employee_id = list_of_emps(indx)... Update.... Update.. Copyright 2013 Feuerstein and Associates Procedural statement executor Fewer context switches. Update.. Page 73 .

– Same transaction and rollback segment management – Same number of individual SQL statements will be executed. Copyright 2013 Feuerstein and Associates statement_trigger_and_forall. the processing in the SQL engine is almost completely unchanged. • For both FORALL and BULK COLLECT. • Only one difference: BEFORE and AFTER statementlevel triggers only fire once per FORALL INSERT statements. – Not for each INSERT statement passed to the SQL engine from the FORALL statement.Oracle PL/SQL Programming Impact of Bulk Processing in SQL layer • The bulk processing features of PL/SQL change the way the PL/SQL engine communicates with the SQL layer.sql Page 74 .

FETCH cur BULK COLLECT INTO collection(s). Copyright 2013 Feuerstein and Associates Page 75 . • Deposit the multiple rows of data into one or more collections. • Retrieve multiple rows into a collection with a single fetch (context switch to the SQL engine).Oracle PL/SQL Programming BULK COLLECT for multi-row querying SELECT * BULK COLLECT INTO collection(s) FROM table. EXECUTE IMMEDIATE query BULK COLLECT INTO collection(s).

the collection is emptied.Oracle PL/SQL Programming "Good to Know" about BULK COLLECT • NO_DATA_FOUND is not raised when no rows are fetched. • The "INTO" collections are filled sequentially from index value 1. • Cursor FOR loops are automatically optimized to execute at a performance similar to BULK COLLECT. Copyright 2013 Feuerstein and Associates Page 76 . • No need to initialize or extend nested tables and varrays. Done automatically by Oracle. instead. – There are no "gaps" between 1 and the index value returned by the COUNT method.

Iterate through the collection contents with a loop..tst FOR indx IN 1 . l_employees. END LOOP. But what if I need to fetch and process millions of rows? This approach could consume unacceptable amounts of PGA memory. END.Oracle PL/SQL Programming An "unlimited" BULK COLLECT Declare a nested table of records to hold the queried data. Fetch all rows into collection sequentially. starting with 1. Copyright 2013 Feuerstein and Associates DECLARE TYPE employees_aat IS TABLE OF employees%ROWTYPE. l_employees employees_aat.sql bulkcollect. bulkcoll.COUNT LOOP process_employee (l_employees(indx)). BEGIN SELECT * BULK COLLECT INTO l_employees FROM employees. Page 77 .

Oracle PL/SQL Programming Limit rows returned by BULK COLLECT CREATE OR REPLACE PROCEDURE bulk_with_limit (deptno_in IN dept. END LOOP. emps emp_tt.deptno%TYPE) IS CURSOR emps_in_dept_cur IS SELECT * FROM emp WHERE deptno = deptno_in.sql Copyright 2013 Feuerstein and Associates Page 78 . BEGIN OPEN emps_in_dept_cur. memory used with the BULK COLLECT operation. CLOSE emps_in_dept_cur. EXIT WHEN emps. Definitely the preferred approach in production applications with large or varying datasets. END bulk_with_limit. bulklimit. process_emps (emps). LOOP Use the LIMIT clause with the FETCH emps_in_dept_cur INTO to manage the amount of BULK COLLECT INTO emps LIMIT 1000.COUNT = 0. TYPE emp_tt IS TABLE OF emps_in_dept_cur%ROWTYPE.

Oracle PL/SQL Programming Details on that LIMIT clause • The limit value can be a literal or a variable. – I suggest using passing the limit as a parameter to give you maximum flexibility. Copyright 2013 Feuerstein and Associates Page 79 . • A limit of 100 seems like a good default value. a larger LIMIT could help. – Setting it to 500 or 1000 doesn't seem to make much difference in performance. however. • With very large volumes of data and small numbers of batch processes.

Oracle PL/SQL Programming Anti-Pattern Exercise Time! PL/SQL Challenge .Play a Quiz Anti-Pattern PL/SQL BULK COLLECT Copyright 2013 Feuerstein and Associates Page 80 .

Oracle PL/SQL Programming BULK COLLECT Conclusions • BULK COLLECT improves performance of queries that retrieve more than one row. Copyright 2013 Feuerstein and Associates Page 81 .1 and higher. the optimizer automatically optimizes cursor FOR loops to run at performance levels similar to BULK COLLECT. • On 10. • So leave your cursor for loops in place if they contain no DML operations or seem to be running fast enough. • Use the LIMIT clause to avoid excessive PGA memory consumption. – Explicit BULK COLLECTs will usually run a little faster than cursor for loops optimized to BC.

high_value UPDATE employee SET salary = newsal_in WHERE employee_id = list_of_emps (indx).. deletes or merges to FORALL statements.) IS BEGIN FORALL indx IN low_value .Oracle PL/SQL Programming Use FORALL for repeated DML operations PROCEDURE upd_for_dept (.. updates.. END. Bind array • Convert loops that contain inserts. • Header looks identical to a numeric FOR loop.sql Page 82 . – Implicitly declared integer iterator – At least one "bind array" that uses this iterator as its index value. – You can also use a different header "style" with INDICES OF and VALUES OF (covered later) Copyright 2013 Feuerstein and Associates forall_timing.sql forall_examples.

• The collection must be indexed by integer. • Indexes cannot be expressions.Oracle PL/SQL Programming More on FORALL • Use any type of collection with FORALL. – Each FORALL is its own "extended" DML statement. • The bind array must be sequentially filled. forall_restrictions. • Only one DML statement is allowed per FORALL.sql Copyright 2013 Feuerstein and Associates Page 83 . – Unless you use the INDICES OF or VALUES OF clause.

bulk_rowcount. – Not to be relied on when used with LOG ERRORS.Oracle PL/SQL Programming How many rows were modified? • SQL%ROWCOUNT returns total number of rows modified by entire FORALL.sql Copyright 2013 Feuerstein and Associates Page 84 . – A "pseudo-collection" of integers. no methods are defined for this element. • Use the SQL%BULK_ROWCOUNT cursor attribute to determine how many rows are modified by each statement.

Oracle PL/SQL Programming Anti-Pattern Exercise Time! PL/SQL Challenge .Play a Quiz Anti-Pattern PL/SQL FORALL Basics Copyright 2013 Feuerstein and Associates Page 85 .

however. • Now.sql Copyright 2013 Feuerstein and Associates Page 86 ..) IS BEGIN FORALL indx IN INDICES OF list_of_emps UPDATE employee SET salary = newsal_in WHERE employee_id = list_of_emps (indx). you can bind sparse collections by using INDICES OF and VALUES OF in the FORALL header. the binding arrays in a FORALL statement must be sequentially filled. 10g_indices_of*.Oracle PL/SQL Programming Using FORALL with Sparse Collections • Prior to Oracle10g R2.. PROCEDURE upd_for_dept (.sql 10g_values_of*.

Oracle PL/SQL Programming

FORALL and DML Errors
• FORALLs typically execute a large number of DML
statements.
• When an exception occurs in one of those DML
statement, the default behavior is:
– That statement is rolled back and the FORALL stops.
– All (previous) successful statements are not rolled
back.

• What if you want the FORALL processing to continue,
even if an error occurs in one of the statements?
• Just add the SAVE EXCEPTIONS clause and then check
the SQL%BULK_EXCEPTIONS array.
Copyright 2013 Feuerstein and Associates

Page 87

Oracle PL/SQL Programming

Using SAVE EXCEPTIONS
• For each exception raised, Oracle populates the
SQL%BULK_EXCEPTIONS pseudo-collection of
records, with two fields.
– ERROR_INDEX: the number of the DML statement that
failed (sequentially generated).
– ERROR_CODE: the number (positive) for the error that was
raised
– Unfortunately, it does not store the error message.

• When the FORALL statement completes, if at least
one exception occurred, Oracle then raises ORA24381.
Copyright 2013 Feuerstein and Associates

bulkexc.sql
bulkexc_indices_of*.sql

Page 88

Oracle PL/SQL Programming

FORALL with SAVE EXCEPTIONS
• Add SAVE EXCEPTIONS to enable FORALL to
suppress errors at the statement level.
If any exception is
encountered,
Oracle raises 24381 when done.

CREATE OR REPLACE PROCEDURE load_books (
books_in IN book_obj_list_t)
IS
bulk_errors EXCEPTION;
PRAGMA EXCEPTION_INIT ( bulk_errors, -24381 );
BEGIN
Allows processing of all
FORALL indx IN books_in.FIRST..books_in.LAST
statements, even after
SAVE EXCEPTIONS
an error occurs.
INSERT INTO book values (books_in(indx));
EXCEPTION
WHEN bulk_errors THEN
Iterate through
FOR indx in 1..SQL%BULK_EXCEPTIONS.COUNT
"pseudo-collection"
LOOP
log_error (SQL%BULK_EXCEPTIONS(indx).ERROR_INDEX
of errors.
, SQL%BULK_EXCEPTIONS(indx).ERROR_CODE);
END LOOP;
END;
Copyright 2013 Feuerstein and Associates

bulkexc.sql
bulkexc.sql
bulkexc_indices_of*.sql

Page 89

how do you "communicate" from one to the other? Copyright 2013 Feuerstein and Associates Page 90 .Oracle PL/SQL Programming Converting to Bulk Processing • Let's take a look at the process by which you go from "old-fashioned" code to a bulk processing-based solution. • From integrated row-by-row to phased processing • With multiple DML statements in loop.

... CREATE OR REPLACE PROCEDURE upd_for_dept ( dept_in IN employees.salary . rec. BEGIN FOR rec IN emp_cur LOOP BEGIN INSERT INTO employee_history ....sql Copyright 2013 Feuerstein and Associates Page 91 .Oracle PL/SQL Programming The "Old Fashioned" Approach • Cursor FOR loop with two DML statements. END.salary).employee_id. trap exception.. adjust_compensation (rec. newsal_in IN employees. and keep on going. EXCEPTION WHEN OTHERS THEN log_error. cfl_to_bulk_0. END LOOP. END upd_for_dept. UPDATE employees SET salary = rec.salary%TYPE) IS CURSOR emp_cur .department_id%TYPE .

Relational Table Phase 1: Bulk collect from table(s) to collection Phase 2: Modify contents of collection according to requirements Relational Table Phase 3: FORALL from collection to table Copyright 2013 Feuerstein and Associates Page 92 . row-by-row approach to a phased approach.Oracle PL/SQL Programming A phased approach with bulk processing • Change from integrated.

salaries. Copyright 2013 Feuerstein and Associates cfl_to_bulk_0. update_employee. insert_history. following the phased approach. salaries). END LOOP.COUNT = 0. hire_dates).sql Page 93 . Phase 1: Get Data Phase 3: Push Data Phase 2: Massage Data Phase 3: Push Data BEGIN OPEN employees_cur. EXIT WHEN employee_ids.sql file contains the converted program. LOOP fetch_next_set_of_rows ( bulk_limit_in. END upd_for_dept.Oracle PL/SQL Programming Translating phases into code • The cfl_to_bulk_5.sql cfl_to_bulk_5. adj_comp_for_arrays (employee_ids. employee_ids.

Oracle PL/SQL Programming Anti-Pattern Exercise Time! PL/SQL Challenge .Play a Quiz Anti-Pattern PL/SQL FORALL Advanced Copyright 2013 Feuerstein and Associates Page 94 .

– But remember that Oracle will automatically optimize cursor FOR loops to BULK COLLECT efficiency. – Almost always the fastest way to execute repeated SQL operations in PL/SQL. • Watch out for the impact on PGA memory! Copyright 2013 Feuerstein and Associates Page 95 .Oracle PL/SQL Programming Conclusions – Bulk Processing • FORALL is the most important performance tuning feature in PL/SQL. – No need to convert unless the loop contains DML or you want to maximally optimize your code. • You trade off increased complexity of code for dramatically faster execution.

Copyright 2013 Feuerstein and Associates Page 96 . BEGIN SELECT * INTO l_employee FROM employees WHERE employee_id = employee_id_in.Oracle PL/SQL Programming Multiple Retrievals of Same Data • Final challenge: how can we avoid querying the same (unchanged) data again and again? – Our applications are filled with the same or similar SQL statements. often getting the same rows. END. CREATE OR REPLACE PROCEDURE do_stuff_with_employee ( employee_id_in IN employees.employee_id%TYPE) IS l_employee employees%ROWTYPE.

• Options for PL/SQL Programmers include: – Materialized views (well.Oracle PL/SQL Programming Caching is the Answer! • Store unchanged values in a cache. and then retrieve data from that cache. sort of) – PGA caching with packages – SGA caching with the function result cache Copyright 2013 Feuerstein and Associates Page 97 .

– A PGA-based cache. • Not a reliable technique for Web-based (usually stateless) applications Copyright 2013 Feuerstein and Associates Page 98 . you can cache multiple rows of data. specific to each session. their state persists in your session. • And if you declare a collection at the package level. – Very useful for static datasets like materialized views.Oracle PL/SQL Programming PGA-Based Caching • When you declare variables at the package level.

Database is not needed.tst Page 99 .pkg / emplu. Request data from database PGA Application Requests Data Subsequent accesses Database / SGA Data returned to application Data retrieved from cache Data found in cache. Data returned to application Application Function PGA Application Requests Data Copyright 2013 Feuerstein and Associates emplu.Oracle PL/SQL Programming Avoiding Unnecessary SGA Lookups First access Data retrieved from cache Pass Data to Cache Database / SGA Application Function Not in cache.

– Not a reliable technique for stateless application (Internet) • Very difficult to share cache across sessions in the same instance.. – One possibility involves DBMS_PIPE.Oracle PL/SQL Programming PGA Caching: Things to keep in mind • Must use package-level data so that it persists. – Memory is consumed by the PGA and so is multiplied for all users of the application. – Small.. • Useful under specific scenarios. • Very difficult to update the cache once the data source is changed.pkg Page 100 . static dataset – Single or small number of batch processes Copyright 2013 Feuerstein and Associates syscache. – Especially by/from. other sessions. Possible to use DBMS_ALERT..

Oracle PL/SQL Programming Anti-Pattern Exercise Time! PL/SQL Challenge .Play a Quiz Anti-Pattern PL/SQL PGA Caching with Packages Copyright 2013 Feuerstein and Associates Page 101 .

Copyright 2013 Feuerstein and Associates Page 102 . – stored in the SGA – shared across sessions – purged of dirty data automatically • You can use and should use it to retrieve data from any table that is queried more frequently than updated..11g Oracle PL/SQL Programming The Oracle 11g Function Result Cache • 11g offers a far superior caching solution than PGA caching in 11g: the Function Result Cache. • This cache is..

• When a call is made to function. • If a match is found. cached data is returned. the function is executed and the inputs and return data are cached. the cache is marked invalid and will be re-built. Oracle compares IN argument values to the cache. the function is not executed. • If no match. • If changes to a "relies on" table are committed.sql Page 103 .11g Oracle PL/SQL Programming How the Function Result Cache Works • Add the RESULT_CACHE clause to your function's header. Copyright 2013 Feuerstein and Associates 11g_frc_demo.

RELIES_ON is then ignored.. END emplu11g.2. END onerow. Oracle will automatically determine all tables on which the function relies. • Add RESULT_CACHE keyword to header of function in both specification and body.. CREATE OR REPLACE PACKAGE BODY emplu11g IS FUNCTION onerow (employee_id_in IN employees.. Copyright 2013 Feuerstein and Associates Page 104 .11g Oracle PL/SQL Programming Minimal Impact on Code with Result Cache CREATE OR REPLACE PACKAGE emplu11g IS FUNCTION onerow (employee_id_in IN employees. • RELIES_ON clause is deprecated in 11.employee_id%TYPE) RETURN employees%ROWTYPE RESULT_CACHE.employee_id%TYPE) RETURN employees%ROWTYPE RESULT_CACHE RELIES_ON (employees) IS . END emplu11g.

11g Oracle PL/SQL Programming Performance Impact of Result Cache • The result cache is stored in the SGA.* Page 105 . • Let's find out! Copyright 2013 Feuerstein and Associates 11g_emplu*. – Even if the statement is parsed and the data blocks are already in the SGA. • So it should be much faster than executing a query. • So we should expect it be slower than a PGAbased cache. • But accessing result cache data does not require going through the SQL engine.

dependent caches are ignored.sql Page 106 . • Caching is not performed for complex types: records with CLOBs. collections. – But Oracle is optimistic! • The cache is not related to SQL statements in your function. Copyright 2013 Feuerstein and Associates 11g_frc_demo. etc. – The cache will not override your own changed data. – It only keeps track of the input values and the RETURN clause data.11g Oracle PL/SQL Programming Result Cache – Things to Keep in Mind • If you have uncommitted changes in your session.

Play a Quiz Anti-Pattern PL/SQL Function Result Cache Basics Copyright 2013 Feuerstein and Associates Page 107 .Oracle PL/SQL Programming Anti-Pattern Exercise Time! PL/SQL Challenge .

sql 11g_frc_vpd2. Copyright 2013 Feuerstein and Associates 11g_frc_session_state. – References to SYSDATE.11g Oracle PL/SQL Programming Result Cache and Session Dependencies • Functions with session-specific dependencies must be "result-cached" with great care.sql 11g_frc_vpd.sql Page 108 . reliance on NLS_DATE_FORMAT. time zone changes – Application contexts (calls to SYS_CONTEXT) – Virtual private database configurations • Solution: move dependencies into parameter list (the "unique index" for the cache).

• DBMS_RESULT_CACHE management package • v$RESULT_CACHE_* performance views Copyright 2013 Feuerstein and Associates show_frc_dependencies. then the LRU algorithm negates the point of the cache.sp Page 109 .11g Oracle PL/SQL Programming Managing the Result Cache • Oracle offers a number of ways to manage the result cache and tune it to your specific application needs: • RESULT_CACHE_SIZE initialization parameter – If the cache is too small.

2 • Oracle keeps track of table dependencies on a per-result level. Copyright 2013 Feuerstein and Associates 11g_frc_dependencies.11g Oracle PL/SQL Programming Fine Grained Dependencies in 11. • A change to a table could invalidate just a subset of the results in the cache. – It's not all or nothing .sql Page 110 . – Each result cached could have a different set of dependencies.when your function's different logic paths could "hit" different tables.sql 11g_frc_dependencies2.

Oracle PL/SQL Programming Anti-Pattern Exercise Time! PL/SQL Challenge .Play a Quiz Anti-Pattern PL/SQL Advanced Function Result Cache Topics Copyright 2013 Feuerstein and Associates Page 111 .

upgrading will be expensive and slow.sql Page 112 . • If you hide your queries behind functions." Copyright 2013 Feuerstein and Associates 11g_frc_encapsulation. • But how easy will it be for you to apply it? • If you write/duplicate queries throughout your code. and you can upgrade "instantly.Oracle PL/SQL Programming Make It Easy on Yourself • I hope you will agree that the result cache is a great feature. you have a single point of definition.

Oracle PL/SQL Programming The Power of Names Copyright 2013 Feuerstein and Associates Page 113 .

a symbol that is associated with an underlying set of data. – And if you know God's true name…wow! • Names exist in a hierarchy of abstraction. – Human -> Woman -> Mother -> Joan Feuerstein Copyright 2013 Feuerstein and Associates Page 114 . – Le Guin's Earthsea cycle a classic example – Let's not forget about Rumplestiltskin.Oracle PL/SQL Programming What's In a Name? • A name is an abstraction. • A common concept in history is: knowing the "true name" of something or someone gives one power over that thing.

AI? – Most would agree that the brain identifies and stores data. which can be referenced by name.org and On Intelligence. – Most have failed dismally. sorting through all the data our senses provide. Copyright 2013 Feuerstein and Associates Page 115 .Oracle PL/SQL Programming What's in a brain? • Humans constantly seek models to describe how the brain works. • Seems fairly clear that our brain is a big pattern analysis engine. – One interesting consequence: stereotyping/prejudice unavoidable feature of "being human"? – Check out: numenta. Where art thou. – Build plans of action based on those patterns.

Everyone knows you're a person Copyright 2013 Feuerstein and Associates Page 116 .Oracle PL/SQL Programming Pattern Analysis and Abstraction • Or to bring it back to our favorite species….

Oracle PL/SQL Programming Names in Software • Names are crucial to human efforts to transform our world to make it more convenient and more comfortable. – 1. Improve maintainability: make it easier to read and understand code. Copyright 2013 Feuerstein and Associates Page 117 . – But what do they do for software? • Names are used in software in two key ways…. Hide information: avoid information overload! – 2.

Copyright 2013 Feuerstein and Associates Page 118 . 24 hour TV.Oracle PL/SQL Programming Hide Information • Information hiding: a key principle of software generally and object orientation in particular. etc. • This is certainly true of complex software." • So we hide details that are not needed at this moment behind a name. • Human brains can handle only so much data. – We live in an age of information overload (internet. – The closest humans come to "world creators.).

Oracle PL/SQL Programming

Improve Maintainability of Code
• Arguably the most important (and most
neglected) aspect of software.
• Factors in maintainability include:
– Self-documentation: comments are bad. :-)
– Single point of definition: repetition is bad.
– Ease (and associated low cost) of change over
time: spaghetti code is bad.

• Let's take a look at features of PL/SQL that
relate to names.
Copyright 2013 Feuerstein and Associates

Page 119

Oracle PL/SQL Programming

Where Names Are Found in PL/SQL
• Where are they not found?
– Software without names is, well, blobby.





Tables, views, columns
Program units and their subprograms
Types…and subtypes
Variables, constants and cursors
Labels for "unnamed" sections of code

Copyright 2013 Feuerstein and Associates

Page 120

Oracle PL/SQL Programming

Guidelines for An Excellent PL/SQL Name
• Has no more than 30 characters. Bummer!
– And finds a nice balance between length and clarity

• Does not rely on CamelNotation.
– Don't fight case insensitivity of SQL-PL/SQL!

• Reflects the information hidden behind the
name.
– A misleading name makes reading code extremely
difficult.

• Standardize the structure of the name.
– Prefixes, suffixes, singular vs. plural
get_the_name_right.sql
Copyright 2013 Feuerstein and Associates

Page 121

• Start with package names. then nested subprogram names. then subprogram names. functions return things.Oracle PL/SQL Programming Program Units and Names • The starting point (leaving aside tables and views) for all PL/SQL developers. Don't put "get" in function name! Copyright 2013 Feuerstein and Associates Page 122 . into which are collected multiple procedures and functions. – Package names: define an area of functionality. – Subprogram names: procs do things.

Oracle PL/SQL Programming Nested Subprograms "extreme" modularization -> high readability • You can declare a procedure or function in any declaration section. – An anonymous block – Another procedure or function • Nested subprograms offer tremendous power to improve readability through information hiding. Copyright 2013 Feuerstein and Associates "table of contents" for subprogram Page 123 .

– Subtypes give application-specific names for commonly-used declaration types.NUMBER_TABLE. Copyright 2013 Feuerstein and Associates plsql_limits. • We can also create our own types. – Declare types in package specs so they can be reused easily. etc.Oracle PL/SQL Programming Types and Subtypes • Oracle defines lots of "generic" types for us to use (NUMBER. as well as the simple but powerful SUBTYPE.* Page 124 .). DBMS_SQL. VARCHAR2.pks string_tracker3.

always define a "subtype" or subset of an existing type with the SUBTYPE statement. to the variable declared with the subtype. – Apply constraints. and nested collections. however. such as numeric ranges.Oracle PL/SQL Programming About SUBTYPEs • You can't always use %TYPE or %ROWTYPE in your declaration. • You can. – Give application-specific names to types. Copyright 2013 Feuerstein and Associates Page 125 . SUBTYPE benefits: – Avoid exposing and repeating constraints. Critical when working with complex structures like collections of records.

* Page 126 . l_big_string VARCHAR2(32767).maxvarchar2. put the explanation into a subtype. define a subtype instead.pks string_tracker3.full_name_t. Copyright 2013 Feuerstein and Associates fullname. l_big_string plsql_limits.Oracle PL/SQL Programming Applying SUBTYPEs • Two key scenarios: – Whenever you are about to write a VARCHAR2(N) or other constrained declaration.pks plsql_limits. – Instead of writing a comment explaining a declaration. preferably in a package specification. Instead of this: Write this: DECLARE l_full_name VARCHAR2(100). DECLARE l_full_name employees_rp.

• You can also declare a cursor in a package specification (a named query. make sure your names reflect the content/usage of your variable. – But watch out! The cursor will persist in your session .sql no_more_hardcoding. in essence). • Use constants to hide literal values. Copyright 2013 Feuerstein and Associates hardcoding. providing a single point of definition. Constants and Cursors • As with program units.you must close it explicitly when done.Oracle PL/SQL Programming Variables.pkg Page 127 .sql pkgcur.

. <<close_orders>> DECLARE l_new_local_var NUMBER := 100. BEGIN . END close_orders.." BEGIN <<per_month_report>> FOR indx IN 1 ." • But you can give them names with labels! – But I recommend that you make them nested subprograms instead. END LOOP per_month_report. – Use Toad's Refactoring tool to make sure you "do it right... Copyright 2013 Feuerstein and Associates Page 128 . 12 LOOP .Oracle PL/SQL Programming Labels for "Unnamed" Code Sections • Nested blocks are "anonymous".. • Loops are "anonymous.

• Back to that same principle: Never Repeat Anything.Oracle PL/SQL Programming The Power of Hiding • Repeat after me: Everything is going to change." – Change the implementation. how you get things done. behind a procedure or function. Aim for Single Point of Definition. Copyright 2013 Feuerstein and Associates Page 129 . and you don't need to change all the places in which it is used. you are "liberated. • When you hide the "mechanics".

Oracle PL/SQL Programming Anti-Pattern Exercise Time! PL/SQL Challenge .Play a Quiz Anti-Pattern PL/SQL Power of Names Copyright 2013 Feuerstein and Associates Page 130 .

• Next. comes great responsibility. – Thanks.Oracle PL/SQL Programming The Power of Names • Names contain an enormous amount of explanatory and manipulative power. • The result? Sparkling clear software that will be given the name: "Excellent Stuff" Copyright 2013 Feuerstein and Associates Page 131 . choose your names with care. Spiderman! • So first maximize opportunities to replace complexity with a name. • With great power.

Oracle PL/SQL Programming Oracle Database 12c PL/SQL Features • More PL/SQL-Only Data Types Cross PL/SQL-to-SQL Interface • Optimizing Function Execution in SQL • The ACCESSIBLE_BY Clause • FETCH FIRST and BULK COLLECT • Privileges/Access Management for Program Units – Grant Roles to Program Units – And INHERIT PRIVILEGES and INHERIT ANY PRIVILEGES – BEQUEATH CURRENT_USER for Views • New Conditional Compilation Directives • Implicit Statement Results • Goodbye. Tiny SQL VARCHAR2! Copyright 2013 Feuerstein and Associates Page 132 .

etc. – Bind records and associative arrays – Use TABLE operator with associative arrays – Can bind Booleans with dynamic PL/SQL. Copyright 2013 Feuerstein and Associates 12c_table*. restricted what functions could be called in SQL. PL/SQL-only datatypes could not be bound in dynamic SQL statements. those rules are greatly relaxed.sql Page 133 .Oracle PL/SQL Programming More PL/SQL-Only Data Types Cross PL/SQL-to-SQL Interface • Prior to 12c. but you cannot bind Booleans into SQL statements. • Now.sql 12c_bind*.

sql 12c_udf.sql & 12c_udf2.Oracle PL/SQL Programming Optimizing Function Execution in SQL • That seems like an awfully good idea! • Two methods: – WITH clause that defines a function – UDF pragma that gives more options to the compiler • WITH FUNCTION: define a function directly within your SQL statement. – Say goodbye to nasty context switch! Copyright 2013 Feuerstein and Associates 12c_with_function*.sql Page 134 .

Oracle PL/SQL Programming FETCH FIRST N for BULK COLLECT • BULK COLLECT now supports an optional FETCH FIRST clause. 12c_fetch_first. reducing the complexity of common "Top-N" queries. – Limits the number of rows that a query returns.sql Copyright 2013 Feuerstein and Associates Page 135 . • FETCH FIRST is provided primarily to simplify migration from third-party databases to Oracle Database.

12c_accessible_by. PROCEDURE do_that. END.Oracle PL/SQL Programming The ACCESSIBLE_BY Clause • ACCESSIBLE_BY extends the concept of "privacy" for package subprograms. private_pkg.sql Copyright 2013 Feuerstein and Associates Page 136 . PACKAGE private_pkg ACCESSIBLE BY (public_pkg) IS PROCEDURE do_this. END. • Use it to define a "whitelist" of program units that can invoke a package's subprograms. PACKAGE BODY public_pkg IS PROCEDURE do_only_this IS BEGIN private_pkg. END.do_that.do_this.

etc.) at run-time. let's review definer and invoker rights. it runs under the privileges of the schema in which the program was compiled or defined.Oracle PL/SQL Programming Privilege-Related Features • First. view. based on the currently-connect user and its privileges (directly granted or available through roles). • Definer Rights – Whenever you executed a stored program. • Invoker Rights – Oracle resolves all data references (table. Copyright 2013 Feuerstein and Associates Page 137 .

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

it's all or nothing.. unless you write code in the package to essentially recreate roles programmatically. each user has own copy of table(s).and now you do! Copyright 2013 Feuerstein and Associates Page 139 ..Oracle PL/SQL Programming Problems with Definer Rights • Deployment & maintenance – Must install module in all remote databases where needed – In some databases. – Difficult to audit privileges • Sure would be nice to have a choice. requiring copy of stored module • Security – No declarative way to restrict privileges on certain modules in a package -.

.destroy(.. Copyright 2013 Feuerstein and Associates modify destroy User/Data schema PROCEDURE mng_account IS BEGIN ... Central Code schema PACKAGE acct_mgr make AUTHID CURRENT_USER .)..acct_mgr.FROM accounts WHERE.. END.Oracle PL/SQL Programming "Reflection" Capability of Invoker Rights • With invoker rights.. yet have all references to data structures "reflect back" into your own schema. accounts table Page 140 . code.. you can execute code owned by another schema.

so you finetune the privileges available to the invoker of a program unit. • Most helpful when the program unit executes dynamic SQL (no privilege checking till runtime). they affect the privilege checking of SQL statements that the unit issues at run time. – Instead. Copyright 2013 Feuerstein and Associates invdefinv.sql 12c_grant_roles_units.sql 12c_roles_for_program_units. – So the program unit executes with the privileges of both its own roles and any other currently enabled roles.1) • You can now grant roles to program units.sql Page 141 . • Roles granted to a program unit do not affect compilation. – Helpful when you don't want the invoker to inherit all of the definer's privileges.Oracle PL/SQL Programming Grant Roles to Program Units (12.

it would always be run under the privileges of the view's owner." 12c_bequeath. and not that of the function.sql Copyright 2013 Feuerstein and Associates Page 142 . if your view executed a function. – Even if the function was defined with AUTHID CURRENT_USER • Add the BEQUEATH CURRENT_USER clause and then the invoker right's mode of the function will be "honored.1.Oracle PL/SQL Programming BEQUEATH CURRENT_USER for Views • Prior to 12.

– INHERT PRIVILEGES granted to all schemas Copyright 2013 Feuerstein and Associates 12c_inherit_privileges. all works as before. – On a schema-level basis • You can say. in effect: "All schemas but SCOTT can use my privileges when running X.Oracle PL/SQL Programming INHERIT PRIVILEGES and INHERIT ANY PRIVILEGES • More fine-tuning for privilege management! • You can override AUTHID and BEQUEATH settings by revoking INHERIT PRIVILEGES." • After upgrade.sql Page 143 .

Copyright 2013 Feuerstein and Associates Page 144 . • $$PLSQL_UNIT_OWNER – Returns the name of the owner of the current program unit. • $$PLSQL_UNIT_TYPE – Returns the type of the program unit – Inside an anonymous block or non-DML trigger.Oracle PL/SQL Programming New Conditional Compilation Directives • Oracle has added two new directives. Returns NULL if an anonymous block. returns "ANONYMOUS BLOCK".

– Not that there was ever all that much…. with 12.Oracle PL/SQL Programming Implicit Statement Results • I hate when a SQL Server developer says "Ha. ha.1. I can do this and you can't. there's one less thing that developer can talk about.sql Copyright 2013 Feuerstein and Associates Page 145 ." • Well. • We can now create a procedure that will implicitly display the result of a SQL statement. – And it breathes some life back into DBMS_SQL! 12c_implicit_results.

SQL's VARCHAR2 and NVARCHAR2 have been extended to 32K as well! • Note: SQL has these maximum sizes only if the MAX_STRING_SIZE initialization parameter is set to EXTENDED. while in SQL. • Now. Tiny SQL VARCHAR2! • It sure has been irritating that PL/SQL supports VARCHAR2s up to 32K in size (after which . the maximum was 4000. 12c_sql_varchar2. you must switch over to CLOBs).Oracle PL/SQL Programming Goodbye.sql Copyright 2013 Feuerstein and Associates Page 146 .

but a solid improvement on an already robust language. • My favorite by far: ability to use TABLE with associative arrays.Oracle PL/SQL Programming Oracle12c New PL/SQL Features • Nothing earth-shattering. Copyright 2013 Feuerstein and Associates Page 147 . – Improved integration with SQL – Better support for migration from TransactSQL and other database languages – Fine-tuning of privileges management and access control.

– It's going to be around for YEARS to come! Copyright 2013 Feuerstein and Associates Page 148 .Oracle PL/SQL Programming Make the Most of Oracle PL/SQL! • This language is not evolving very rapidly these days (less change than in SQL). • Make sure that you are aware of key new (and existing) features. and put them to use. • Always prioritize the maintainability of your code.