0% found this document useful (0 votes)
45 views24 pages

How When Writes QL in Pls QL

sql

Uploaded by

Divya Srinivasan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
45 views24 pages

How When Writes QL in Pls QL

sql

Uploaded by

Divya Srinivasan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 24

Best Practice PL/SQL

When and How to Write


SQL in Oracle PL/SQL

Steven Feuerstein
Oracle Architect, Applied PL/SQL
[email protected]
twitter: @sfonplsql
blog: stevenfeuersteinonplsql.blogspot.com
Copyright 2014 Oracle and/or its aliates. All rights reserved. |

Do we really need to talk about SQL in PL/SQL?


Consider the typical (and oIen silent) conversaKons we have about SQL.
It's so easy to write
SQL in PL/SQL!

Oracle will opKmize it all for me


automagically.

This INSERT will never raise a


DUP_VAL error.

What we
say about
SQL

No one else will ever need to write a


SQL statement like this.

Copyright 2014 Oracle and/or its aliates. All rights reserved. |

SQL/Database Most CriKcal Part of ApplicaKon


SQL statements directly reect our business models.
And those models are always changing. And then there's the data.

SQL statements cause most of the performance problems in our


applicaKons.
Tuning SQL and the way that SQL is called in PL/SQL overwhelms all other
consideraKons.

Many runKme errors in applicaKons result from integrity and check


constraints on tables.
Finally, just because NoSQL and Node.js and whatever else devalue SQL
and database, doesn't mean they're right.
But it does mean we have our work cut out for us. StarKng with us.
Copyright 2014 Oracle and/or its aliates. All rights reserved. |

Page 3

We Take SQL for Granted


So we write SQL whenever and wherever
we need it, over and over again.

Order Entry Applica7on


We don't set rules on how, when and where


SQL should be wricen.

The Backend
Order
Table

We don't stay current.


Fall back into PL/SQL (or "worse") when going
gets tough.

Item
Table
Customer
Table

The result? Slow, buggy code that is dicult to opKmize and maintain.

Copyright 2014 Oracle and/or its aliates. All rights reserved. |

Two key SQL quesKons for your next project


At a minimum, before starKng your next applicaKon, ask yourselves
explicitly:

1. Are we taking full advantage of SQL, parKcularly new features in our


version?

You should do as much as possible in "pure" SQL.

2. Do we want standards, or should we just keep on doing whatever


we want, whenever we want?

That way, you are at least making a conscious decision.

Copyright 2014 Oracle and/or its aliates. All rights reserved. |

Fully leverage SQL in your PL/SQL code


Oracle conKnually adds signicant new funcKonality to the SQL language.
If you don't keep up with SQL capabiliKes, you will write slower, more
complicated PL/SQL code than is necessary.
I am a precy good example of what you don't want to do or how to be.
And, by the way, table funcKons are a great way to escape from SQL!

So take the Kme to refresh your understanding of Oracle SQL in Oracle


Database 11g and Oracle Database 12c.
Start with the New Features list in the doc set.
See if anything stands out immediately and dive in from there.
Also check Tom Kyte's resources on OTN and AskTom.
Copyright 2014 Oracle and/or its aliates. All rights reserved. |

Some exciKng recently added SQL features


AnalyKcal FuncKons
Such as LAG, LEAD, ranking etc.; these allow you to look to previous and following rows to calculate dierences.

WITH clause (subquery factoring)


Allows the deniKon of 'views' inside a query that can be used and reused; they allow procedural top-down
logic inside a query
In 12.1 you can also dene a func4on inside a query!

Flashback query
No more need for journal tables, history tables, etc.

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 funcKon call.

select d.deptno
, (select count(*)
from emp e where e.deptno =
d.deptno) number_staff from dept
Copyright 2014 Oracle and/or its aliates. All rights reserved. |

So do we want standards for wriKng SQL?


Please, say yes!
Without standards we will not be able to take full advantage of Oracle Database and
we will not be (as) successful (as we could be).

In this presentaKon, I will focus on a small number of the most important


best pracKces.
Many excellent and detailed recommendaKons from Bryn Llewellyn
Search for "Doing SQL from PL/SQL: Best and Worst PracKces"

But rst I will try and convince you that....


Every SQL statement you write is a hard-coding.
And SQL hard-codings are the worst kind.
Copyright 2014 Oracle and/or its aliates. All rights reserved. |

How is a SQL statement dierent from a literal?


BEGIN
SELECT a.col1, b.col2, pkg.func (c.col3)
FROM this a, that b, the_other c ...

BEGIN
IF salary_in > 1505000 THEN ...

When a literal changes, you must nd all occurrences and change them.
With values like "45098", a global search/replace gets the job done (if you are very careful).

When a table changes, you must nd all the SQL statements that are aected.
When your hard-coding is a DML statement, you've got a serious problem.
How can you be sure you found all the same logical occurrences?

Logically, a SQL statement and a literal value are the same, when it comes to hard-
coding.
So if you don't like hard-coded literals, you should hate hard-coded SQL.

Copyright 2014 Oracle and/or its aliates. All rights reserved. |

Writing SQL is all about defining the Now


Every SQL statement you
write says:
At this moment in time,
here's how to capture
this relationship or
business rule.
But our ERDs are quite
complex and they don't
get simpler over time.

10

Copyright 2014 Oracle and/or its aliates. All rights reserved. |

What to do about SQL hard coding


You have to (and should) write SQL statements in your applicaKon.
Use Oracle Database!

The quesKon becomes: where you should put those statements?


DON'T
Put SQL statements in Java or .Net or Javascript. Fight the good ght!

DO
Hide complex queries behind views, and use those views in reports.
Put all your other SQL statements in PL/SQL packages (cursors, subprograms),
hiding the SQL behind an API of procedures and funcKons.

Copyright 2014 Oracle and/or its aliates. All rights reserved. |

Hide SQL statements behind a PL/SQL API


Think of SQL as a service that is provided to you,
not something you write.

Application
Code

Or if you write it, you put it somewhere so that it can be


easily found, reused, and maintained.

This service consists of views and programs


dened in the data access layer.
Views hide complex query construcKon
Packaged APIs for tables, transacKons and business
enKKes

That intermediate ("intercept") layer oers


tremendous benets.
Copyright 2014 Oracle and/or its aliates. All rights reserved. |

Intermediate Layer

Order
Table

Item
Table

With a data access layer, I can...


Change my implementaKon with minimal impact on applicaKon code.
The underlying data model is constantly changing.
We can depend on Oracle to add new features.
We learn new ways to take advantage of PL/SQL.

Improve my SQL-related error handling.


Do you take the Kme to handle dup_val_on_index for INSERTs,
too_many_rows for SELECT INTOs, etc?

Greatly increase my producKvity


I want to spend as much Kme as possible implemenKng business
requirements.

Copyright 2014 Oracle and/or its aliates. All rights reserved. |

11g_frc_demo.sql
11g_frc_encapsulaKon.sql
11g_emplu.*

A simple example of hiding SQL behind a function


CREATE OR REPLACE PROCEDURE process_employee
(
employee_id IN number)
IS
l_name VARCHAR2(100);
BEGIN
SELECT last_name || ',' ||
first_name
INTO l_name
FROM employee
WHERE employee_id =
process_employee.employee_id;
...
END;

CREATE OR REPLACE PACKAGE employee_rp


AS
SUBTYPE fullname_t
IS VARCHAR2 (200);
-- The formula
FUNCTION fullname (
l employee.last_name%TYPE,
f employee.first_name%TYPE
)
RETURN fullname_t;
-- Retrieval function
FUNCTION fullname (
employee_id_in IN
employee.employee_id%TYPE
)
RETURN fullname_t;
END;

l_name employee_rp.fullname_t;
BEGIN
l_name :=
employee_rp.fullname (
employee_id_in);
...
END;

14

Copyright 2014 Oracle and/or its aliates. All rights reserved. |

fullname.pkg
explimpl.pkg

Data Access Layer Tips and Gotchas


Give yourself the "space" to do it right.
Doesn't take all that much Kme to move query to funcKon and call funcKon.
But it does take some discipline and paKence.

Tom Kyte strongly recommends transacKon APIs.


I agree and add that table APIs can also be very helpful, when used correctly.

Do not call a "cascade" of funcKons, when you can execute a single query (in a possibly
new funcKon).
It's kind of like of nested cursor FOR loops instead of a join! Both bad news....

Generate as much of the code as you can to ensure consistency.


Bad
Cascade

IS
l_employee := employees_pkg.one_row (employee_id_in);
l_department := departments_pkg.one_row (l_employee.department_id);
BEGIN
Copyright 2014 Oracle and/or its aliates. All rights reserved. |

15

Other RecommendaKons for SQL in PL/SQL


When fetching a single row, use SELECT-INTO (and put it inside a funcKon).
Or EXECUTE IMMEDIATE-INTO with a dynamic query.

When fetching and changing mulKple rows, use bulk processing features:
BULK COLLECT and FORALL.
Covered in separate webinar in this series.

For dynamic SQL...


Bind rather than concatenate whenever possible.
Always EXECUTE IMMEDIATE a variable and include an excepKon handler so that the
variable can be analyzed easily.
ExecuKng dynamic DDL? Make it an autonomous transacKon!
Copyright 2014 Oracle and/or its aliates. All rights reserved. |

16

Always use SELECT-INTO for single row fetches


CURSOR emp_cur IS
SELECT last_name || ',' || first_name
INTO l_name
FROM employees
WHERE employee_id = employee_id_in;
BEGIN
OPEN emp_cur;
FETCH emp_cur INTO l_name;
CLOSE emp_rec;

BEGIN
SELECT
INTO
FROM
WHERE

last_name || ',' || first_name


l_name
employees
employee_id = employee_id_in;

BEGIN
l_name := employees_pkg.full_name (employee_id_in);

A great example of how "everything changes" and we must update our


thinking.
"Long, long ago..." an explicit cursor was faster than an implicit. Ancient history.

SELECT-INTO and EXECUTE IMMEDIATE-INTO....


Perform becer, more accurately "tell the story", raise errors when reality doesn't t
the story.
Copyright 2014 Oracle and/or its aliates. All rights reserved. |

17

Bind rather than concatenate with dynamic SQL


When you concatenate....
Your new, dierent SQL statement must be parsed;
It is more vulnerable to SQL injecKon;
It is much harder to read and maintain.

Bind all variables instead.


Much higher likelihood that the parsed SQL statement can be "reused".
You can't inject into a bind variable.
The resulKng code is much simpler and more readable.

Copyright 2014 Oracle and/or its aliates. All rights reserved. |

usebinding.sp
useconcat*.sp

18

EXECUTE IMMEDIATE a variable, not an expression


The hardest part about dynamic SQL is gexng that string right.
Missing a comma, space between clauses, etc.

If you construct the string inside EXECUTE IMMEDIATE, it's "lost".


Instead, assign to a variable and EXECUTE IMMEDIATE that.
Then when something goes wrong, you can log/display the variable in your
excepKon handler.
The problem is usually quite obvious.

dropwhatever.sp

Copyright 2014 Oracle and/or its aliates. All rights reserved. |

19

Dynamic DDL commits, so make it autonomous


Every parse (and certainly execute) of a DDL statement causes an implicit
commit in your session.
Dynamic DDL should be done with great care in a producKon applicaKon.
Can cause a cascading ripple of invalidaKons.

You can "limit" the eect of the implicit commit to just that DDL statement
by adding the AUTONOMOUS_TRANSACTION pragma.
Oh, and you should also probably use AUTHID CURRENT_USER.
That way, you ensure that the eect of the dynamic DDL (and SQL) is on the invoking,
not dening, schema.
dropwhatever.sp

Copyright 2014 Oracle and/or its aliates. All rights reserved. |

20

When and How to Write SQL - Conclusions


Leverage SQL fully.
Reserve PL/SQL for the logical ow and requirements that cannot be met with set-
oriented SQL.
Keep up to date on the many powerful enhancements to SQL.

Avoid repeKKon of SQL statements.


Signals a loss of control in your applicaKon.
Makes it very hard to opKmize and maintain your code.
Hide your SQL behind views and package APIs.

SET STANDARDS for wriKng SQL in your applicaKons!


Copyright 2014 Oracle and/or its aliates. All rights reserved. |

21

Some Useful Websites for PL/SQL Developers


asktom.oracle.com: Tom Kyte's famed Q&A on Oracle Database
oracle.com/plsql: starKng point for Oracle's resources on PL/SQL.
plsqlchallenge.com: quizzes on PL/SQL, SQL, database design, logic and
more
oracle-developer.net: Adrian Billington's repository of arKcles
Oracle-BASE.com: Tim Hall's set of resources and scripts
All My Code available here:
oracle.com/webfolder/technetwork/tutorials/plsql/sfdemo.zip
or here: goo.gl/FPG79Z
My PL/SQL blog: stevenfeuersteinonplsql.blogspot.com
My PL/SQL twicer handle: @sfonplsql
Copyright 2014 Oracle and/or its aliates. All rights reserved. |

Copyright 2014 Oracle and/or its aliates. All rights reserved. |

23

You might also like