Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Steve.

Asked: March 17, 2005 - 9:51 am UTC

Last updated: March 18, 2005 - 8:03 am UTC

Version: 9.2.0.6

Viewed 1000+ times

You Asked

Tom,
Are there any issues to be aware of or drawbacks/gotchas to adding some logic, beyond a default value assignment, to the variable declaration section of a stored procedure as opposed to putting the logic in the body?

e.g. v_todate date := trunc(nvl(pi_todate, to_date('1-JAN-2199','DD-MON-YYYY')));

VS. (method 2, in the body)

v_todate := trunc(nvl(pi_todate, to_date('1-JAN-2199','DD-MON-YYYY')));

VS. (method 3, in the body)

if pi_todate is null or pi_todate = '' then
v_todate := to_date('1-JAN-2199','DD-MON-YYYY');
else
v_todate := trunc(pi_todate);
end if;


I've had to update several stored procedure for a new version of our application. All of the assignments were done similarly to method 3 above which just got too confusing to mentally interpret quickly, so I changed the ones I could to method 2, then after a week or so to the first method, because it seemed a natural place to do it. I haven't seen any documentation/books with examples like this, they just refer to assigning defaults in declaration section, so I was wondering about consequences.



Thank you,
Steve

and Tom said...

I always do method 1 whenever I can. You are initializing a variable, whatever it takes.

Method 3 in this case probably "marginally, a tiny bit" performed faster. nvl() is the reason. Nvl() evaluates both inputs and then assigns. the if then else would just evaluate one of the functions.

there is also this side effect possible (not in your example, but in general)

ops$tkyte@ORA9IR2> declare
2 x number := nvl( 1/1, 1/0 );
3 begin
4 null;
5 end;
6 /
declare
*
ERROR at line 1:
ORA-01476: divisor is equal to zero
ORA-06512: at line 2


ops$tkyte@ORA9IR2> declare
2 x number;
3 begin
4 if ( 1/1 is null )
5 then
6 x := 1/0;
7 else
8 x := 1/1;
9 end if;
10 end;
11 /

PL/SQL procedure successfully completed.



if one of the arguments to nvl is "an error waiting to happen if it were evaluated" the if then else might avoid it.


But -- all of that aside, if I can initialize the value, i do it that way.

Rating

  (6 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

beware exceptions

Alberto Dell'Era, March 17, 2005 - 2:33 pm UTC

There's nothing in the q that suggests that exception sections were used in the original stored procedures, but if that's the case, beware that exceptions raised in the declaration section are not caught by the sp exception section, so by simply moving initializations to the declaration section you are changing the behaviour of the application:

dellera@ORACLE9I> create or replace function test (x number)
2 return number
3 is
4 l_temp number;
5 begin
6 l_temp := 1/x;
7 return l_temp;
8 exception
9 when zero_divide then
10 return 0;
11 end;
12 /

Function created.

dellera@ORACLE9I> select test (0) from dual;

TEST(0)
----------
0

dellera@ORACLE9I> create or replace function test (x number)
2 return number
3 is
4 l_temp number := 1/x;
5 begin
6 return l_temp;
7 exception
8 when zero_divide then
9 return 0;
10 end;
11 /

Function created.

dellera@ORACLE9I> select test (0) from dual;
select test (0) from dual
*
ERROR at line 1:
ORA-01476: divisor is equal to zero
ORA-06512: at "DELLERA.TEST", line 4

(I've read this in one of Tom's books by the way)

hth

Tom Kyte
March 17, 2005 - 3:51 pm UTC

yes, there are subtle differences, that is another one.

Difference in exception handling

Scot, March 17, 2005 - 2:47 pm UTC

MYDBA@ORCL >
MYDBA@ORCL > create procedure test1(p_one varchar2)
2 is
3 l_var number := p_one;
4 begin
5 dbms_output.put_line('l_var: ' || l_var);
6 exception when others then
7 dbms_output.put_line('Boom thrown from inside test 1');
8 end;
9 /

Procedure created.

MYDBA@ORCL >
MYDBA@ORCL > create procedure caller1
2 is
3 begin
4 test1('Hello');
5 exception when others then
6 dbms_output.put_line('Boom thrown from inside caller 1');
7 end;
8 /

Procedure created.

MYDBA@ORCL >
MYDBA@ORCL > create procedure test2(p_one varchar2)
2 is
3 l_var number;
4 begin
5 l_var := p_one;
6 dbms_output.put_line('l_var: ' || l_var);
7 exception when others then
8 dbms_output.put_line('Boom thrown from inside test 2');
9 end;
10 /

Procedure created.

MYDBA@ORCL >
MYDBA@ORCL > create procedure caller2
2 is
3 begin
4 test2('Hello');
5 exception when others then
6 dbms_output.put_line('Boom thrown from inside caller 2');
7 end;
8 /

Procedure created.

MYDBA@ORCL >
MYDBA@ORCL > exec caller1;
Boom thrown from inside caller 1

PL/SQL procedure successfully completed.

MYDBA@ORCL > exec caller2;
Boom thrown from inside test 2

PL/SQL procedure successfully completed.

MYDBA@ORCL >
MYDBA@ORCL > drop procedure caller1;

Procedure dropped.

MYDBA@ORCL > drop procedure caller2;

Procedure dropped.

MYDBA@ORCL > drop procedure test1;

Procedure dropped.

MYDBA@ORCL > drop procedure test2;

Procedure dropped.

MYDBA@ORCL >
MYDBA@ORCL > set echo off;


Hey...yeah...what Alberto said

Scot, March 17, 2005 - 2:50 pm UTC

I probably learned that from Tom as well.

Your example is probably a bit more realistic than mine.


Good to know.

Steve, March 17, 2005 - 3:26 pm UTC

That's good reassurance.

Thanks.
Steve

:= vs. default

Matthias Rogel, March 18, 2005 - 2:37 am UTC

most useful.

by the way, is there any difference between
:=
vs.
default

Or do they exactly behave the same ?

Tom Kyte
March 18, 2005 - 6:59 am UTC

they are the same

All good

Steve, March 18, 2005 - 8:03 am UTC

Alberto thanks for the note on exception handling (actually the lack of handling).

All of what I put in the declaration was along the lines changing a null to a specific value. But it is something I need to be cognisant of in the future if I try something along the lines of the examples given.

Thanks again.
Steve

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library