Documente Academic
Documente Profesional
Documente Cultură
www.plsqlchannel.com
27+ hours of detailed video training
on Oracle PL/SQL
www.stevenfeuerstein.com
Monthly PL/SQL newsletter
www.toadworld.com/SF
Quest Software-sponsored portal
for PL/SQL developers
Compiler Optimization
• As of Oracle Database 10g, the compiler will
automatically optimize your code.
– Default setting of 2 is best, but 11g also offers a
new level 3 "inlining" optimization.
• The optimizer takes advantage of "freedoms"
to re-order the execution of statements.
– In essence, changing the route that the runtime
engine takes to get from point A to point B in your
code.
for i in 1 .. 10 loop
A := B + C;
...
end loop; Automatic relocation of a loop invariant.
Avoid repetitive computations.
A := B + C;
for i in 1 .. 10 loop
...
end loop;
10g_optimize_cfl.sql
Copyright 2013 Feuerstein and Associates Page 8
Oracle PL/SQL Programming
CASE
• Added to PL/SQL in 9i (earlier in SQL), you can
use CASE statements and expressions to
replace IF statements.
• CASE expressions are especially good at
replacing multiple IF statements with a single
expression.
– When building a complex string for example.
• Most lengthy ELSIFs should be replaced with a
CASE statement.
case*.sql
Autonomous Transactions
• Default transaction behavior in PL/SQL is at the session
level
– A commit saves all outstanding changes in your session.
– A rollback erases all outstanding changes in your session.
• Define a PL/SQL block as an "autonomous transaction" to
control the scope of commit/rollback.
– Any changes made within that block will be saved or reversed
without affecting the outer or main transaction.
• Two rules for autonomous transactions:
– Must include the autonomous transaction pragma.
– Must commit or rollback before exiting the block if any DML
statements were executed.
• Most common application: error logging
Collections
• Collections are PL/SQL's implementation of
arrays.
• All collections in PL/SQL are single
dimensional lists or sets.
• They provide the foundation for many
performance optimization features.
– Bulk processing, table functions and more.
• They can consume lots of PGA memory.
Collection Methods
• The term method is used to describe
procedures and functions that defined in a class
or object type.
– You invoke a method by attaching it, using dot
notation, to the name of the type/class or to an
instance of the class.
• Collection methods are procedures and
functions that are attached to a collection
variable.
– First introduction of object-oriented syntax in
PL/SQL – way back in Oracle 7.3.4!
Collections Methods
• COUNT
– number of elements currently defined in collection.
• EXISTS
– TRUE if the specified index values is defined.
• FIRST/LAST
– lowest/highest index values of defined rows.
• NEXT/PRIOR
– defined index value after/before the specified index value .
• LIMIT
– max. number of elements allowed in a VARRAY.
• DELETE
– remove elements from a collection
• EXTEND
– add elements to a nested table or varray
nested_table_example.sql
Copyright 2013 Feuerstein and Associates Page 19
Oracle PL/SQL Programming
Performance penalty
for many “context
switches”
Copyright 2013 Feuerstein and Associates Page 25
Oracle PL/SQL Programming
Update... Update...
Update... Update...
Update... Update...
Update... Update...
Update... Update...
Update... Fewer context switches, Update...
same SQL behavior
Copyright 2013 Feuerstein and Associates Page 27
Oracle PL/SQL Programming
statement_trigger_and_forall.sql
Copyright 2013 Feuerstein and Associates Page 28
Oracle PL/SQL Programming
More on FORALL
• Use the SQL%BULK_ROWCOUNT cursor
attribute to determine how many rows are
modified by each statement.
– SQL%ROWCOUNT returns total for FORALL.
• Use SAVE EXCEPTIONS and
SQL%BULK_EXCEPTIONS to execute all
statements, saving errors for later.
– You will need to handle ORA-24381.
• When collections may be sparse, use INDICES
OF or VALUES OF.
bulk_rowcount.sql
bulkexc.sql
10g_indices_of*.sql
Copyright 2013 Feuerstein and Associates 10g_values_of.sql Page 31
Oracle PL/SQL Programming
Relational
Table
Phase 3: FORALL from collection to table
Copyright 2013 Feuerstein and Associates Page 34
Oracle PL/SQL Programming
cfl_to_bulk_0.sql
Copyright 2013 Feuerstein and Associates cfl_to_bulk_5.sql Page 35
Oracle PL/SQL Programming
11g_frc_demo.sql
Copyright 2013 Feuerstein and Associates Page 37
11g Oracle PL/SQL Programming
11g_emplu*.*
Copyright 2013 Feuerstein and Associates Page 38
11g Oracle PL/SQL Programming
tabfunc_scalar.sql
Copyright 2013 Feuerstein and Associates
tabfunc_streaming.sql Page 41
Oracle PL/SQL Programming
tabfunc_pipelined.sql
Resources http://www.oracle-developer.net/display.php?id=426
http://www.oracle-developer.net/display.php?id=427
http://www.dbprof.com/index.php?option=com_jdownloads&Itemid=57&view=viewcategory&catid=3
Package Initialization
• The initialization section:
PACKAGE BODY pkg
– Is defined after and outside of any IS
programs in the package. PROCEDURE proc IS
BEGIN
– Is not required. In fact, most packages you END;
build won't have one.
– Can have its own exception handling FUNCTION func RETURN
section. BEGIN
END;
• Useful for: BEGIN
...initialize...
– Performing complex setting of default or END pkg;
initial values.
– Setting up package data which does not
change for the duration of a session.
BEGIN after/outside
– Confirming that package is properly of any program
instantiated. defined in the pkg.
init.pkg
init.tst
Copyright 2013 Feuerstein and Associates datemgr.pkg Page 56
Oracle PL/SQL Programming
Overloading in Packages:
key API/usability technique myproc
• Overloading (static polymorphism): two or more
myfunc
programs with the same name, but different
signature. myproc
– You can overload in the declaration section of any
PL/SQL block, including the package body (most
common).
• Overloading is a critical feature when building
comprehensive programmatic interfaces (APIs) or
components using packages.
– If you want others to use your code, you need to make
that code as smart and as easy to use as possible.
– Overloading transfers the "need to know" from the user
to the overloaded program.
Compare:
DBMS_OUTPUT and p packages dynamic_polymorphism.sql
Copyright 2013 Feuerstein and Associates Page 57
Oracle PL/SQL Programming
ambig_overloading.sql
Copyright 2013 Feuerstein and Associates Page 60
Oracle PL/SQL Programming
Modularization Choices
• You can choose from:
– Schema-level procedure or function
– Public packaged subprogram
– Private packaged subprogram
– Nested subprogram
• Avoid schema-level programs; put all your code in
packages.
– Entire package is loaded into memory
– Each package provides a "namespace" in which to
organize related code.
• Use nested subprograms to improve readability
and maintainability of your bodies.
Extreme Modularization
(Write tiny chunks of code)
• Spaghetti code is the bane of
a programmer's existence.
• It is impossible to understand
and therefore debug or
maintain code that has long, Organize your
twisted executable sections. code so that the
executable
• Fortunately, it is really easy to
section has no
make spaghetti code a thing more than fifty
of the past. lines of code.
Explanation of Subprograms
• Function calls_are_unhandled: takes no arguments,
returns TRUE if there is still at least one unhandled
call, FALSE otherwise.
• Function current_caseload: returns the number of
calls (case load) assigned to that employee.
• Function avg_caseload_for_dept: returns the average
number of calls assigned to employees in that
department.
• Procedure assign_next_open_call: assigns the
employee to the call, making it handled, as opposed
to unhandled.
FUNCTION current_caseload (
employee_id_in IN employees.employee_id%TYPE) RETURN PLS_INTEGER
IS BEGIN ... END current_caseload;
FUNCTION avg_caseload_for_dept (
employee_id_in IN employees.employee_id%TYPE) RETURN PLS_INTEGER
IS BEGIN ... END current_caseload;
PROCEDURE assign_next_open_call (
employee_id_in IN employees.employee_id%TYPE)
IS BEGIN ... END assign_next_open_call;
BEGIN
Should I copy and paste? No! I should extract the program and
expand its scope.
PROCEDURE show_caseload (
department_id_in IN departments.department_id%TYPE)
IS BEGIN ... END show_caseload; distribute show_
_calls caseload
PROCEDURE distribute_calls (
department_id_in IN departments.department_id%TYPE
)
IS BEGIN ... END distribute_calls;
END;
current_
caseload
• Now current_caseload is at the package
level and can be called by any program in
the package.
locmod_step_by_step.sql
Copyright 2013 Feuerstein and Associates Page 72
Oracle PL/SQL Programming
hardcoding2.sql
constant_vs_function.sql
Copyright 2013 Feuerstein and Associates Page 81
Oracle PL/SQL Programming
soft_code_literals.sql
this. END;
RAISE;
no_more_hardcoding.sql
Copyright 2013 Feuerstein and Associates Page 87
Oracle PL/SQL Programming
fetch_into_record.sql
Copyright 2013 Feuerstein and Associates Page 88
Oracle PL/SQL Programming
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.
subtype_examples.sql
Copyright 2013 Feuerstein and Associates Page 90
Oracle PL/SQL Programming
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 fullname.pks
Write plsql_limits.pks
l_full_name employees_rp.full_name_t;
this: l_big_string plsql_limits.maxvarchar2; string_tracker3.*
Conclusions
• Declarations offer a danger of hard-coding of
both datatype and constraint on that type.
• Assume that over time everything will change.
• Apply the same "single point of definition"
principle to your declarations.
– Use %TYPE and %ROWTYPE whenever possible.
– Fall back on subtypes to define application specific
types and PL/SQL limitations.
sqlcode.sql
sqlcode_test.sql
Copyright 2013 Feuerstein and Associates Page 95
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 100
Oracle PL/SQL Programming
Logging Errors
• We usually, but not always, want to write error
information out to a log table. How's this?
WHEN NO_DATA_FOUND
THEN
l_code := SQLCODE;
INSERT INTO errlog
VALUES ( l_code
, 'No company for id ' || TO_CHAR ( v_id )
, 'fixdebt', SYSDATE, USER );
WHEN OTHERS
THEN
l_code := SQLCODE; l_errm := SQLERRM;
INSERT INTO errlog
VALUES (l_code, l_errm, 'fixdebt', SYSDATE, USER );
RAISE;
END;
sf_trace*.*
watch.pkg
dbms_application_info_demo.sql
SQL as a Service
• Think of SQL as a service that is provided to you, not
something you write.
– Or if you write it, you put it somewhere so that it can be
easily found, reused, and maintained.
code_injection.sql
Copyright 2013 Feuerstein and Associates Page 118
Oracle PL/SQL Programming
Conclusions
• SQL statements are among the most critical
parts of your application.
– They change frequently, they consume lots of
resources, result in many errors.
• You should have a clearly defined set of
guidelines about when, where and how to
write SQL.
• Most important: Don't repeat SQL statements.
– Most good practices will follow more easily if you
manage to avoid SQL hard-coding.
Program Socially
• Never code alone.
– Writing code by yourself results in
much buggier code than if you had someone with
whom to consult; to ask questions; to help, in turn.
– It's OK to ask for help.
– Follow the 30 minute rule.
• Automated code review in PL/SQL
– Compile-time warnings
– Leverage the data dictionary views
– PL/Scope
REM If you want to enable warning message number 06002 and all warnings in
REM the performance category, and treat 5005 as a "hard" compile error:
ALTER PROCEDURE my_procedure SET plsql_warnings =
'enable:06002', 'enable:performance', 'ERROR:05005';
plw6017.sql
plw5005.sql
plscope_demo_setup.sql
plscope_all_idents.sql
plscope_var_declares.sql
plscope_gvar_declares.sql
plscope_var_changes.sql
Copyright 2013 Feuerstein and Associates Page 142
Oracle PL/SQL Programming
plscope_unused_exceptions.sql
plscope_hierarchy.sql
plscope_naming_conventions.sql
plscope_helper_setup.sql
plscope_helper.pkg
www.plsqlchannel.com
27+ hours of detailed video training
on Oracle PL/SQL
www.stevenfeuerstein.com
Monthly PL/SQL newsletter
www.toadworld.com/SF
Quest Software-sponsored portal
for PL/SQL developers