How to make OUT parameters optional ?

 

OUT and IN OUT parameters of procedures can’t be optional – they can’t be assigned with any default values like NULL, ‘AAA’, 10 or something like that:

 
...
procedure out_p (r out number := null) … /* Wrong syntax*/
...

 

But sometimes it can be needed. The real question from one of the forums was:

 

I am having a procedure with multiple out parameters. At the time of calling the procedure all the OUT parameters may not be required. I need to skip a few of the OUT parameters at the time of calling.

I know it is possible to make IN parameters in a PL/SQL procedure optional. But how to do the same for OUT parameters?

I do not want to create overloaded procedures to achieve it. Because in that case the number of procedures should be as many number of combinations of out parameters. That would lead to around 10/15 overloaded procedures
.”

 

One of the work-around is to combine OUT parameters
into the record and get one such OUT parameter each time
instead of variable number of OUT parameters. We can control what
particular fields of record should have values:

 
SQL> create or replace package test_pkg
  2  is
  3    type e_rec is record (
  4     ename emp.ename%type := 'KING',
  5     sal emp.sal%type := 5000,
  6     empno emp.empno%type := 7369
  7    );
  8    procedure get_rec(idx in number, rc out e_rec);
  9  end;
 10  /

Package created.

SQL> create or replace package body test_pkg
  2  is
  3    procedure get_rec(idx in number, rc out e_rec)
  4    is
  5    begin
  6      if idx = 1 then
  7         rc.ename := 'SMITH';
  8         rc.sal := NULL;
  9         rc.empno := NULL; 
 10      elsif idx = 2 then
 11         rc.sal := 1000;
 12         rc.ename := NULL;
 13         rc.empno := NULL;
 14      else
 15         rc.empno := 7777;
 16         rc.sal := NULL;
 17         rc.ename := NULL;
 18      end if;
 19    end;
 20  end;
 21  /

Package body created.
 

In the example above we replaced three potential OUT parameters – ename, sal, empno - with one record which combines all three. So:

 
SQL> declare
  2   a test_pkg.e_rec;
  3  begin
  4   test_pkg.get_rec(1,a);
  5   dbms_output.put_line('ename = ' || a.ename || ', sal = ' || a.sal ||
  6   ', empno = ' || a.empno);
  7   test_pkg.get_rec(2,a);
  8   dbms_output.put_line('ename = ' || a.ename || ', sal = ' || a.sal ||
  9   ', empno = ' || a.empno);
 10   test_pkg.get_rec(3,a);
 11   dbms_output.put_line('ename = ' || a.ename || ', sal = ' || a.sal ||
 12   ', empno = ' || a.empno);
 13   test_pkg.get_rec(4,a);
 14   dbms_output.put_line('ename = ' || a.ename || ', sal = ' || a.sal ||
 15   ', empno = ' || a.empno);
 16  end;
 17  /
ename = SMITH, sal = , empno =
ename = , sal = 1000, empno =
ename = , sal = , empno = 7777
ename = KING, sal = 5000, empno = 7369

PL/SQL procedure successfully completed.
 

 

As we can see, we also can assign default values to OUT parameters there using record type declaration syntax.

What if we want to keep default values only for a part of parameters ? In this case we can use one IN and one OUT parameter:

 
SQL> create or replace package test_pkg
  2  is
  3    type e_rec is record (
  4     ename emp.ename%type := 'KING',
  5     sal emp.sal%type := 5000,
  6     empno emp.empno%type := 7369
  7    );
  8    procedure get_rec(idx in number, rc out e_rec);
  9    procedure get_rec(idx in number, rc out e_rec, irc in e_rec);
 10  end;
 11  /

Package created.

SQL> create or replace package body test_pkg
  2  is
  3    procedure get_rec_inn(idx in number, rc in out e_rec)
  4    is
  5    begin
  6      if idx = 1 then
  7         rc.ename := 'SMITH';
  8         rc.sal := NULL;
  9         rc.empno := NULL;
 10      elsif idx = 2 then
 11         rc.sal := 1000;
 12         rc.ename := NULL;
 13         rc.empno := NULL;
 14      elsif idx = 3 then
 15         rc.empno := 7777;
 16         rc.sal := NULL;
 17         rc.ename := NULL;
 18      end if;
 19    end;
 20  
 21    procedure get_rec(idx in number, rc out e_rec)
 22    is
 23    begin
 24      get_rec_inn(idx,rc);
 25    end;
 26  
 27  
 28    procedure get_rec(idx in number, rc out e_rec, irc in e_rec)
 29    is
 30    begin
 31      rc := irc;
 32      get_rec_inn(idx,rc);
 33    end;
 34  
 35  end;
 36  /

Package body created.

 

And now:

 
SQL> declare
  2   a test_pkg.e_rec;
  3  begin
  4   
  5   test_pkg.get_rec(4,a); 
  6   dbms_output.put_line('ename = ' || a.ename || ', sal = ' || a.sal ||
  7   ', empno = ' || a.empno);
  8  
  9   a.ename := 'ALLEN';
 10  
 11   test_pkg.get_rec(4,a,a);
 12   dbms_output.put_line('ename = ' || a.ename || ', sal = ' || a.sal ||
 13   ', empno = ' || a.empno);
 14  
 15  end;
 16  /
ename = KING, sal = 5000, empno = 7369
ename = ALLEN, sal = 5000, empno = 7369

PL/SQL procedure successfully completed.

 

 

© Dmitry Nikiforov 2005
Hosted by uCoz