Oracle Magazine - September/October 2007 - Marcelo Machado
Oracle Magazine - September/October 2007 - Marcelo Machado
Oracle Magazine - September/October 2007 - Marcelo Machado
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
ASK TOM<br />
exception handler. I wrote<br />
There’s a programming construct,<br />
WHEN OTHERS, in PL/SQL that I wish<br />
weren’t there.<br />
Well, I knew <strong>Oracle</strong> could never<br />
really remove this language feature—but<br />
<strong>Oracle</strong> certainly has made it safer. Just<br />
to reiterate why I wish this programming<br />
construct did not exist, I’ll quote<br />
myself again:<br />
But the problem I see is that far too<br />
many people use the WHEN OTHERS<br />
clause without following it by a RAISE or<br />
RAISE_APPLICATION_ERROR call. That<br />
effectively hides the error. In reality, the<br />
error happened, but it was not handled in<br />
any meaningful way; it was just ignored—<br />
silently. The invoker of your code has no<br />
idea that something went horribly wrong<br />
and that your code failed, and he or she<br />
typically thinks that everything was, in<br />
fact, successful.<br />
Many times—many more times than<br />
I can recall or count—“quirky” behavior<br />
in a PL/SQL program unit is found to be<br />
caused by the improper use of a WHEN<br />
OTHERS clause—one that is not followed<br />
by RAISE. The error was hidden,<br />
error handling was effectively disabled,<br />
and the outcome is typically logically<br />
corrupt data (the application did not do<br />
its job) or the wrong answer.<br />
Now, in <strong>Oracle</strong> Database 11g, I can<br />
easily find the offending bits of code.<br />
When I suspect that an exception is<br />
being raised and hidden in this fashion,<br />
I’ll be able to verify my hunch rapidly.<br />
Consider this innocuous procedure:<br />
SQL> create table t( x varchar2(4000) );<br />
Table created.<br />
SQL> create or replace<br />
2 procedure maintain_t<br />
3 ( p_str in varchar2 )<br />
4 as<br />
5 begin<br />
6 insert into t<br />
7 ( x ) values<br />
8 ( p_str );<br />
9 exception<br />
10 when others<br />
11 then<br />
12 -- call some log_error() routine<br />
13 null;<br />
14 end;<br />
15 /<br />
Procedure created.<br />
It’s as simple as can be. Nothing<br />
should go wrong, but in case it does, I’ll<br />
log the error by using a utility routine<br />
I’ve developed. That’ll write a nice<br />
error message somewhere (hopefully!),<br />
but whoever invokes this routine will<br />
have no idea that an exception that was<br />
not expected—and that could not be<br />
fixed—happened. (I see code like this<br />
time after time after time.) Now when<br />
someone calls this routine,<br />
SQL> exec maintain_t( rpad( ‘x’, 4001,<br />
‘x’ ) );<br />
PL/SQL procedure successfully completed.<br />
it sure looks successful, but it wasn’t:<br />
SQL> select * from t;<br />
no rows selected<br />
This is where confusion comes in:<br />
people get on the phone; they write<br />
e-mails; they say “<strong>Oracle</strong> Database is<br />
broken; the transaction succeeds, but<br />
the data is wrong.” In fact, the problem<br />
is the hidden error. Now, to find these<br />
errors in <strong>Oracle</strong> Database 11g, I will<br />
simply ask people to perform the following<br />
operation on their code first:<br />
SQL> alter procedure maintain_t compile<br />
2 PLSQL_Warnings = ‘enable:all’<br />
3 reuse settings<br />
4 /<br />
SP2-0805: Procedure altered with<br />
compilation warnings<br />
SQL> show errors procedure maintain_t<br />
Errors for PROCEDURE MAINTAIN_T:<br />
LINE/COL ERROR<br />
-----------––––– –––––––––––––––––––––––––––––––––––––––<br />
9/8 PLW-06009: procedure<br />
“MAINTAIN_T” OTHERS handler<br />
does not end in RAISE or<br />
RAISE_APPLICATION_ERROR<br />
And instantly you’ll have a list of<br />
applications—and the source code<br />
88 SEPTEMBER/OCTOBER <strong>2007</strong> ORACLE.COM/ORACLEMAGAZINE<br />
lines—to immediately go to and add a<br />
simple RAISE to see where this hidden<br />
error is coming from. Job done.<br />
IT’S THE LITTLE THINGS. . . .<br />
There’s a saying that goes, “It’s the little<br />
things in life that really make a difference.”<br />
So I’ll close with a little thing<br />
that will make your coding life a bit<br />
easier and the PL/SQL language a bit<br />
more complete:<br />
SQL> create sequence this_is_nice;<br />
Sequence created.<br />
SQL> declare<br />
2 n number;<br />
3 begin<br />
4 n := this_is_nice.nextval;<br />
5 dbms_output.put_line( n );<br />
6 end;<br />
7 /<br />
1<br />
PL/SQL procedure successfully completed.<br />
Compare that to what would have<br />
happened in <strong>Oracle</strong> Database 10g and<br />
prior releases. In <strong>Oracle</strong> Database 11g,<br />
there’s no more selecting a sequence<br />
FROM DUAL. PL/SQL is that much<br />
more complete.<br />
Tom Kyte has worked for <strong>Oracle</strong> since 1993. He is a<br />
vice president in the <strong>Oracle</strong> Public Sector group and<br />
the author of Expert <strong>Oracle</strong> Database Architecture:<br />
9i and 10g Programming Techniques and Solutions<br />
(Apress, 2005) and Effective <strong>Oracle</strong> by Design (<strong>Oracle</strong><br />
Press, 2003), among others.<br />
ASK Tom<br />
<strong>Oracle</strong> Vice President Tom Kyte answers your most<br />
difficult technology questions. Highlights from that<br />
forum appear in this column.<br />
asktom.oracle.com<br />
READ more about<br />
<strong>Oracle</strong> Database 11g<br />
otn.oracle.com/products/database<br />
READ more Tom<br />
Expert <strong>Oracle</strong> Database Architecture: 9i and 10g<br />
Programming Techniques and Solutions<br />
amazon.com/exec/obidos/tg/detail/-/<br />
1590595300/<br />
DOWNLOAD<br />
<strong>Oracle</strong> Database 11g<br />
otn.oracle.com/technology/software