Professional Documents
Culture Documents
Steven Feuerstein
PL/SQL Evangelist, Quest Software steven.feuerstein@quest.com
Copyright 2000-2009 Steven Feuerstein - Page 1
PL/SQL Obsession
http://www.ToadWorld.com/SF
Download and use any of my scripts (examples, performance scripts, reusable code) from the same location: the demo.zip file. filename_from_demo_zip.sql You have my permission to use all these materials to do internal trainings and build your own applications.
But remember: they are not production ready. Modify them to fit your needs and then test them!
Copyright 2000-2006 Steven Feuerstein - Page 2
More generally, hard-coding is closely tied to the problem of repetition in our code.
Copyright 2000-2008 Steven Feuerstein - Page 4
Too bad!
Whenever anything changes, you have to find all the places you explicitly coded it, and fix them.
Copyright 2000-2008 Steven Feuerstein - Page 6
Easy Coding
It's hard fixing hard-codings in multiple places. It'd be easier to fix things in one place. It really does make things easier.
Copyright 2000-2008 Steven Feuerstein - Page 7
Constrained declarations
Especially VARCHAR2(n)
SQL statements
??? Very scary to contemplate to be explained later
Algorithmic details
Example: error logging mechanisms
Copyright 2000-2008 Steven Feuerstein - Page 10
Literal Values
The most commonly recognized form of hard-coding. The only place a literal should appear in your code is in its SPOD. Hide literals behind:
constants functions
Constrained Declarations
You should consider every declaration of the form VARCHAR2(N) to be a bug.
Unless it is the SPOD for that type.
SUBTYPEs
Most everyone knows about %TYPE and %ROWTYPE.
But what if you can't anchor back to a DB element?
You can always use a SUBTYPE to define a "single point of definition" and use that for all subsequent declarations. SUBTYPEs allow you to give application-specific names to types.
Critical when working with complex structures like collections of records, and nested collections.
15
Applying SUBTYPEs
Instead of this:
DECLARE l_full_name VARCHAR2(100); l_big_string VARCHAR2(32767);
What to do?
Learn to recognize rules and formulas. Often they are missed, especially when simple. Hide the logic behind functions.
SQL Statements
Why do I talk about SQL in a presentation on hard coding? Because I believe that every SQL statement that you write is a hard-coding!
I know, it is shocking to contemplate.
And Joe needs to use that same query in his business rule procedure. And so on... And then the three way join turns into a four way join and we have to find all occurrences of this query.
A very tough thing to do!
Copyright 2000-2008 Steven Feuerstein - Page 20
But we should be very careful about where, when and how we write these statements.
Follow the principles; they are your guide. Don't repeat anything!
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.
Application Code
Intermediate Layer
Order Table
Item Table
And usually an "extra stuff" package with custom SQL logic and related code:
<table>_XP
Copyright 2000-2008 Steven Feuerstein - Page 24
qu_outcome_xp.qu_outcomes qu_outcome_xp.int_create_outcomes
Powerful and free option for generating table APIs for use with PL/SQL is the freeware Quest CodeGen Utility.
Quest CodeGen Utility: www.ToadWorld.com/SF
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;
It's easy to "read" but only because it exposes the logging mechanism.
Copyright 2000-2008 Steven Feuerstein - Page 27
Hide how and what you log: shared, generic logging utility This rewrite is based on the Quest Error Manager.
Freeware available at www.ToadWorld.com/SF. You do less work and get more information.
WHEN NO_DATA_FOUND THEN q$error_manager.register_error ( text_in => 'No company for id ' || TO_CHAR ( v_id )); WHEN OTHERS THEN q$error_manager.raise_unanticipated ( name1_in => 'COMPANY_ID', value1_in => v_id); END;
The Oracle11g function result cache The optimal way to query and cache data changes over time.
Explicit and implicit cursors FORALL and BULK COLLECT And now the function result cache
With the Result Cache, you specify declaratively that Oracle not run your function over and over for the same inputs.
Instead return the data previously cached with matching inputs.
Copyright 2000-2008 Steven Feuerstein - Page 29
30
11g_emplu.pkg
Get a promotion
I can improve my application code much more quickly than those who hard-code SQL..... The Result Cache is a great example of this.
32
Your Reward
Elegant, functional code that you and others can maintain easily The respect of your peers A deep sense of satisfaction with a job well done The opportunity to continue making a darned good living mostly from just thinking about stuff.
Copyright 2000-2008 Steven Feuerstein - Page 34