Best Practices For SQL in PLSQL
Best Practices For SQL in PLSQL
Steven Feuerstein
PL/SQL Evangelist, Quest Software
www.ToadWorld.com/SF www.plsqlchallenge.com [email protected]
Copyright 2010 Feuerstein and Associates
PL/SQL Obsession
http://www.ToadWorld.com/SF
Download and use any of my scripts (examples, performance scripts, reusable code) from the demo.zip, available from the same place.
filename_from_demo_zip.sql
You have my permission to use all these materials to do internal trainings and build your own applications. But they should not considered production ready. You must test them and modify them to fit your needs.
Copyright 2010 Steven Feuerstein
Page 1
And some other incredibly fantastic and entertaining websites for PL/SQL
Page 2
Very few development teams have standards for how, when and where to write SQL statements.
We just all take SQL for granted.
Page 4
Many runtime errors result from integrity and check constraints on tables.
Copyright 2010 Steven Feuerstein
Page 5
The Backend
Order Table Customer Table Item Table
As a result, our application code is packed full of SQL statements, with many repetitions and variations.
Worst of all: SQL in .Net and Java!
This makes it very difficult to optimize and maintain the application code.
Copyright 2010 Steven Feuerstein
Page 6
This presentation as a whole forms a reasonable foundation for such standards. Another excellent resource (and source for this presentation):
Doing SQL from PL/SQL: Best and Worst Practices by Bryn Llewellyn, PL/SQL Product Manager http://www.oracle.com/technology/tech/pl_sql/pdf/doing_sql_from_plsql.pdf
Copyright 2010 Steven Feuerstein
Page 7
So take the time to refresh your understanding of Oracle SQL in 10g and 11g.
Page 8
Flashback query
No more need for journal tables, history tables, etc.
SYS_CONNECT_BY_PATH and CONNECT_BY_ROOT for hierarchical queries select d.deptno , (select count(*) Scalar subquery
Adds a subquery to a query like a function call.
Copyright 2010 Steven Feuerstein
SQL as Hard-Coding....huh?
We all agree that hard-coding "magic values" is a bad idea.
When value changes (and it will), you must find all occurrences and update them.
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
Page 12
And usually an "extra stuff" package (_XP) with custom SQL logic and related code.
You can't generate everything.
Page 14
One option for generating table APIs for use with PL/SQL is the freeware Quest CodeGen Utility, available at PL/SQL Obsession:
www.ToadWorld.com/SF
Copyright 2010 Steven Feuerstein
Page 15
Page 16
Page 17
Choice #2. Full encapsulation: no directly granted privileges on tables, only access path is through API. Choice #3. Encapsulate most important tables and run validations against code to identify violations of the API.
Choice #4. Encapsulate queries to prepare for upgrade to Oracle11g and the function result cache.
Copyright 2010 Steven Feuerstein
code_referencing_tables.sql
Page 18
Define tables in other schemas. Grant access via privileges, mostly via EXECUTE on packages that maintain the tables.
Copyright 2010 Steven Feuerstein
Page 19
Sam_Sales
Close Old Orders
OE Data
X
Cannot access table directly.
Orders
Copyright 2010 Steven Feuerstein
Instead of this....
PROCEDURE IS BEGIN SELECT INTO FROM WHERE abc (...)
Write this....
PROCEDURE abc (...) IS BEGIN SELECT e.last_name INTO l_name FROM employees e WHERE e.employee_id = abc.emp_id_in;
Page 21
Page 22
The most important thing to do, however, is to hide your query inside a function.
So when Oracle changes the picture again, you only have to adjust your code in one place (for each query).
expl_vs_impl.sql
Copyright 2010 Steven Feuerstein
Page 23
With BULK COLLECT into a varray if you know there is a maximum limit on the number of rows retrieved. Otherwise, use the LIMIT clause with your BULK COLLECT statement.
Avoid hard-coding: LIMIT can be a variable or parameter.
bulk*coll*.sql
Copyright 2010 Steven Feuerstein
Page 24
forall*.sql
Copyright 2010 Steven Feuerstein
Page 25
Using a collection with the TABLE operator offers best flexibility and performance.
Must be declared at schema level.
in_clause*.sql
Copyright 2010 Steven Feuerstein
Page 26
So whenever possible....
Use correct datatypes to avoid need to convert. Rely on explicit rather than implicit conversions.
explicit_implicit.sql
Copyright 2010 Steven Feuerstein
Page 27