Académique Documents
Professionnel Documents
Culture Documents
Anti-Pattern
PL/SQL
Programming
Steven Feuerstein
steven@stevenfeuerstein.com
www.StevenFeuerstein.com
www.PLSQLChallenge.com
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
www.plsqlchannel.com
27+ hours of detailed video training
on Oracle PL/SQL
www.stevenfeuerstein.com
Monthly PL/SQL newsletter
PL/SQL Fundamentals
Compiler optimization
Context switching in Oracle
Memory management
Performance penalty
for many context
switches
Copyright 2013 Feuerstein and Associates Page 11
Oracle PL/SQL Programming
Anti-Pattern PL/SQL -
Context Switching
Raising Exceptions
Oracle raises exceptions.
You can raise exceptions as well.
Use RAISE to raise an exception.
Use RAISE_APPLICATION_ERROR to pass an
application-specific message back to a user.
You can also define your own exceptions so
that you can raise that exception - and handle
it by name.
With PRAGMA EXCEPTION_INIT.
raise.sql
raise_application_error.sql
Copyright 2013 Feuerstein and Associates Page 21
Oracle PL/SQL Programming
Handling Exceptions
After exception is raised, the block closes and
control is passed to the exception section or
propagates unhandled to an outer block.
Exceptions raised in declaration section are not
handled.
The EXCEPTION section contains one or more
WHEN clauses.
WHEN exc - traps one exception
WHEN exc1 OR exc2 - traps more than one
WHEN OTHERS - traps almost any exception.
info_for_handling.sql
excquiz*.sql
Copyright 2013 Feuerstein and Associates Page 22
Oracle PL/SQL Programming
Anti-Pattern PL/SQL -
Error Management Basics
sqlcode.sql
sqlcode_test.sql
Copyright 2013 Feuerstein and Associates Page 26
Oracle PL/SQL Programming
SQLERRM Details
If you don't pass an argument to SQLERRM, it returns
the error message for the SQLCODE value.
When called outside of an exception handler, always
returns "success" message no error.
You can also pass an error code to SQLERRM and it
will return the generic error message.
The maximum size of a string returned by SQLERRM
is 512 bytes.
When there is a stack of errors, Oracle may truncate the
string returned by SQLERRM.
Oracle recommends you use
DBMS_UTILITY.FORMAT_ERROR_STACK instead.
sqlerrm.sql
DBMS_UTILITY.FORMAT_CALL_STACK
The "call stack" reveals the path taken through
your application code to get to that point.
Very useful whenever tracing or logging
errors.
The string is formatted to show line number
and program unit name.
But it does not reveal the names of subprograms
in packages.
callstack.sql
callstack.pkg
DBMS_UTILITY.FORMAT_ERROR_STACK
This built-in returns the error stack in the
current session.
Possibly more than one error in stack.
Returns NULL when there is no error.
Returns a string of maximum size 2000 bytes
(according to the documentation).
Oracle recommends you use this instead of
SQLERRM, to reduce the chance of truncation.
errorstack.sql
big_error_stack.sql
DBMS_UTILITY.FORMAT_ERROR_BACKTRACE
The backtrace function (new to 10.2) answers the
question: "Where was my error raised?
Prior to 10.2, you could not get this information from
within PL/SQL.
Call it whenever you are logging an error.
When you re-raise your exception (RAISE;) or raise a
different exception, subsequent BACKTRACE calls will
point to that line.
So before a re-raise, call BACKTRACE and store that
information to avoid losing the original line number.
backtrace.sql
bt.pkg
Copyright 2013 Feuerstein and Associates Page 31
Oracle PL/SQL Programming
Anti-Pattern PL/SQL -
Error Management Built-Ins
assoc_array_example.sql
nested_table_example.sql
varray_example.sql
Anti-Pattern PL/SQL -
Collection Methods
collection_of_records.sql
string_tracker0.*
Copyright 2013 Feuerstein and Associates Page 38
Oracle PL/SQL Programming
emulate_primary_key1.sql
emulate_primary_key2.sql
Copyright 2013 Feuerstein and Associates Page 40
Oracle PL/SQL Programming
assoc_array*.sql
assoc_array_perf.tst
Copyright 2013 Feuerstein and Associates string_tracker2.* Page 42
Oracle PL/SQL Programming
Anti-Pattern PL/SQL -
Creative Indexing with Arrays
Nested Collections
The element of a nested collection type is
itself a collection or contains a collection.
Field in record, attribute in object type
Usages for multilevel collections:
Model normalized data structures in PL/SQL
collections
Emulate multidimensional arrays.
The syntax for working with multilevel
collections can be hard to parse (in your
head).
nested_collections.sql
Copyright 2013 Feuerstein and Associates Page 44
Oracle PL/SQL Programming
string_tracker3*.*
Copyright 2013 Feuerstein and Associates Page 45
Oracle PL/SQL Programming
Anti-Pattern PL/SQL -
Nested Collections
favorites_pkg.show_favorites (
'DISTINCT SET', keep_it_simple);
END;
authors.pkg
Copyright 2000-2008 Steven Feuerstein - Page 51 10g_set.sql
Copyright 2013 Feuerstein and Associates Page 51
Oracle PL/SQL Programming
in_clause.*
Copyright 2013 Feuerstein and Associates 10g_member_of.sql Page 52
Oracle PL/SQL Programming
authors.pkg
Copyright 2013 Feuerstein and Associates 10g_submultiset.sql Page 53
Oracle PL/SQL Programming
authors.pkg
10g_union.sql
Copyright 2013 Feuerstein and Associates Page 54
Oracle PL/SQL Programming
10g_intersect.sql
Copyright 2013 Feuerstein and Associates Page 55
Oracle PL/SQL Programming
10g_except.sql
Copyright 2013 Feuerstein and Associates Page 56
Oracle PL/SQL Programming
Anti-Pattern PL/SQL -
Nested Table Features
SQL in PL/SQL
SQL: the heart and soul of any Oracle-based
application.
And also the problem child.
PLSQL: the best place to put your SQL
And the opportunity to create a slow, ugly mess
We'll start with some principles
Move on to key features for executing SQL
inside PL/SQL program units.
BEGIN
FOR employee_r IN ( SELECT last_name
FROM employees
ORDER BY employee_id)
LOOP
IF employee_r.last_name LIKE '%s%'
THEN
DBMS_OUTPUT.put_line (employee_r.last_name);
END IF;
END LOOP;
END;
Anti-Pattern PL/SQL
Maximize SQL
SELECT *
INTO l_manager
FROM employees
WHERE employee_id = l_employee.manager_id;
END;
Copyright 2013 Feuerstein and Associates Page 68
Oracle PL/SQL Programming
Anti-Pattern PL/SQL -
Same SQL Multiple Places
Update... Update...
Update... Update...
Update... Update...
Update... Update...
Update... Update...
Update... Fewer context switches, Update...
same SQL behavior
Copyright 2013 Feuerstein and Associates Page 73
Oracle PL/SQL Programming
statement_trigger_and_forall.sql
Copyright 2013 Feuerstein and Associates Page 74
Oracle PL/SQL Programming
Anti-Pattern PL/SQL -
BULK COLLECT
More on FORALL
Use any type of collection with FORALL.
Only one DML statement is allowed per
FORALL.
Each FORALL is its own "extended" DML
statement.
The collection must be indexed by integer.
The bind array must be sequentially filled.
Unless you use the INDICES OF or
VALUES OF clause.
Indexes cannot be expressions. forall_restrictions.sql
bulk_rowcount.sql
Anti-Pattern PL/SQL -
FORALL Basics
Relational
Table
Phase 3: FORALL from collection to table
Copyright 2013 Feuerstein and Associates Page 92
Oracle PL/SQL Programming
cfl_to_bulk_0.sql
Copyright 2013 Feuerstein and Associates cfl_to_bulk_5.sql Page 93
Oracle PL/SQL Programming
Anti-Pattern PL/SQL -
FORALL Advanced
PGA-Based Caching
When you declare variables at the package
level, their state persists in your session.
A PGA-based cache, specific to each session.
And if you declare a collection at the package
level, you can cache multiple rows of data.
Very useful for static datasets like materialized
views.
Not a reliable technique for Web-based
(usually stateless) applications
Database Application
/ SGA Function
Not in cache; PGA
Request data
from database Application
Requests Data
Data found in
Database cache. Database Application
/ SGA is not needed. Function
PGA
Application
Requests Data
emplu.pkg / emplu.tst
Copyright 2013 Feuerstein and Associates Page 99
Oracle PL/SQL Programming
syscache.pkg
Copyright 2013 Feuerstein and Associates Page 100
Oracle PL/SQL Programming
Anti-Pattern PL/SQL -
PGA Caching with Packages
11g_emplu*.*
Copyright 2013 Feuerstein and Associates Page 105
11g Oracle PL/SQL Programming
Anti-Pattern PL/SQL -
Function Result Cache Basics
11g_frc_session_state.sql
11g_frc_vpd.sql
Copyright 2013 Feuerstein and Associates 11g_frc_vpd2.sql Page 108
11g Oracle PL/SQL Programming
show_frc_dependencies.sp
Copyright 2013 Feuerstein and Associates Page 109
11g Oracle PL/SQL Programming
11g_frc_dependencies.sql
Copyright 2013 Feuerstein and Associates
11g_frc_dependencies2.sql Page 110
Oracle PL/SQL Programming
Anti-Pattern PL/SQL -
Advanced Function Result Cache
Topics
11g_frc_encapsulation.sql
Copyright 2013 Feuerstein and Associates Page 112
Oracle PL/SQL Programming
What's In a Name?
A name is an abstraction, a symbol that is
associated with an underlying set of data.
A common concept in history is: knowing the
"true name" of something or someone gives
one power over that thing.
Le Guin's Earthsea cycle a classic example
Let's not forget about Rumplestiltskin.
And if you know God's true namewow!
Names exist in a hierarchy of abstraction.
Human -> Woman -> Mother -> Joan Feuerstein
What's in a brain?
Humans constantly seek models to describe how
the brain works.
Most have failed dismally. Where art thou, AI?
Most would agree that the brain identifies and stores
data, which can be referenced by name.
Seems fairly clear that our brain is a big pattern
analysis engine, sorting through all the data our
senses provide.
Build plans of action based on those patterns.
One interesting consequence: stereotyping/prejudice
unavoidable feature of "being human"?
Check out: numenta.org and On Intelligence.
Copyright 2013 Feuerstein and Associates Page 115
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.
But what do they do for software?
Names are used in software in two key ways.
1. Hide information: avoid information overload!
2. Improve maintainability: make it easier to read
and understand code.
Hide Information
Information hiding: a key principle of software
generally and object orientation in particular.
Human brains can handle only so much data.
We live in an age of information overload
(internet, 24 hour TV, etc.).
This is certainly true of complex software.
The closest humans come to "world creators."
So we hide details that are not needed at this
moment behind a name.
get_the_name_right.sql
Copyright 2013 Feuerstein and Associates Page 121
Oracle PL/SQL Programming
tremendous power
to improve readability
through information
hiding.
plsql_limits.pks
string_tracker3.*
Copyright 2013 Feuerstein and Associates Page 124
Oracle PL/SQL Programming
About SUBTYPEs
You can't always use %TYPE or %ROWTYPE in your
declaration.
You can, however, always define a "subtype" or
subset of an existing type with the SUBTYPE
statement. SUBTYPE benefits:
Avoid exposing and repeating constraints.
Give application-specific names to types. Critical when
working with complex structures like collections of
records, and nested collections.
Apply constraints, such as numeric ranges, to the variable
declared with the subtype.
Applying SUBTYPEs
Two key scenarios:
Whenever you are about to write a VARCHAR2(N)
or other constrained declaration, define a subtype
instead, preferably in a package specification.
Instead of writing a comment explaining a
declaration, put the explanation into a subtype.
DECLARE
Instead l_full_name VARCHAR2(100);
of this: l_big_string VARCHAR2(32767);
DECLARE
Write
l_full_name employees_rp.full_name_t;
this: l_big_string plsql_limits.maxvarchar2; fullname.pks
plsql_limits.pks
string_tracker3.*
Copyright 2013 Feuerstein and Associates Page 126
Oracle PL/SQL Programming
hardcoding.sql
no_more_hardcoding.sql
pkgcur.pkg
Copyright 2013 Feuerstein and Associates Page 127
Oracle PL/SQL Programming
<<close_orders>>
DECLARE
l_new_local_var NUMBER := 100;
BEGIN
...
END close_orders;
Anti-Pattern PL/SQL -
Power of Names
12c_with_function*.sql
Copyright 2013 Feuerstein and Associates 12c_udf.sql & 12c_udf2.sql Page 134
Oracle PL/SQL Programming
12c_fetch_first.sql
Copyright 2013 Feuerstein and Associates Page 135
Oracle PL/SQL Programming
12c_accessible_by.sql
Copyright 2013 Feuerstein and Associates Page 136
Oracle PL/SQL Programming
Privilege-Related Features
First, let's review definer and invoker rights.
Definer Rights
Whenever you executed a stored program, it runs
under the privileges of the schema in which the
program was compiled or defined.
Invoker Rights
Oracle resolves all data references (table, view,
etc.) at run-time, based on the currently-connect
user and its privileges (directly granted or available
through roles).
12c_bequeath.sql
Copyright 2013 Feuerstein and Associates Page 142
Oracle PL/SQL Programming
12c_inherit_privileges.sql
Copyright 2013 Feuerstein and Associates Page 143
Oracle PL/SQL Programming