Home » SQL & PL/SQL » SQL & PL/SQL » NO COPY parameters
NO COPY parameters [message #634488] Tue, 10 March 2015 15:16 Go to next message
ppatel87
Messages: 5
Registered: November 2014
Junior Member
Hi
I have been trying hard to understand the concept of nocopy in plsql
but not able to reach any conclusion
Can some one tell me by giving a simple example of it
Re: NO COPY parameters [message #634489 is a reply to message #634488] Tue, 10 March 2015 15:22 Go to previous messageGo to next message
BlackSwan
Messages: 26766
Registered: January 2009
Location: SoCal
Senior Member
If you can't understand documentation, why should we waste our time posting same words here & have you not understand them again/still?
Re: NO COPY parameters [message #634490 is a reply to message #634488] Tue, 10 March 2015 15:32 Go to previous messageGo to next message
John Watson
Messages: 8930
Registered: January 2010
Location: Global Village
Senior Member
My advice woud be: do not even think about using NOCOPY. Sure, you can get a tiny saving in memory and performance because it passes the parameters by reference (so no need to copy them, which happens if you pass them by value). However, this is a potential disaster. Google "side effects in C" if you want to take this further.
Re: NO COPY parameters [message #634499 is a reply to message #634490] Tue, 10 March 2015 22:36 Go to previous messageGo to next message
Kevin Meade
Messages: 2103
Registered: December 1999
Location: Connecticut USA
Senior Member
Yes, as John points out, there are only a few reasons to consider using NOCOPY.

Here is a brief description of what it is. As was pointed out by BlackSwan, this is in the manuals.

When you call procedure B from procedure A and you pass to procedure B a parameter, there are two ways to pass it:

1. BY REFERENENCE
2. BY VALUE (the default for PL/SQL)

The default for PL/SQL is #2, BY VALUE. How you pass a variable gives us several points to consider:

1. If you pass BY VALUE (the default), then a copy is made of the value you want to pass and the copy is sent to the called procedure.  But if you pass by reference then you send the memory address of where the value lives to the called procedure which means the called procedure can make changes to your original value since there is no copy of it.

2. If you pass BY VALUE then if something bad happens inside the called procedure and you fail back out to the calling procedure, the original value of your variable is untouched because the called procedure was never working on it; it was given a copy of it.  So any changes it might have made to the copy before it crapped out on you, are simply forgotten along with the copy.

3. But if you pass BY REFERENCE, you give the called procedure the memory address of your parameter's value telling the called procedure that it should manipulate the value at that location.  Thus there is no copy made.  If your called procedure makes changes to the parameter and then the called procedure fails, your calling procedure is stuck with whatever the called procedure did to your parameter value.  This can cause problems if you intend to try and continue on since the value you started with is gone forever.

The drawback of BY VALUE is for very large parameters. Consider for example if you had large PL/SQL arrays, or COLLECTIONS that you were passing. You would have to make a copy of them before you pass them. If you have a 10MB array, then you have to stop and make a 10MB copy of that array before you can pass it around. If it is an IN-OUT parameter then it needs to be copied back to its original location when your called procedure is done; thus in effect, a second copy. So with vary large variables, BY VALUE can be substantially slower because you are making lots of copies of things. Consider a FOR LOOP that iterates of 1 million records which for each record must make a copy of a 10MB array. That is 10GB of copying. OK one might question such an application design but you get the idea right?

I have first hand experience with this, though it is from a time long gone (back in the 8i days (or maybe even earlier)). I was working with large PL/SQL arrays, and when I switched from BY VALUE to BY REFERNECE, it ran 50X faster since most of the work was in the copying of the arrays, not actually doing work with array values.

To demonstrate, consider this code and its result. As you can see, each procedure is the same, they each will simply add 1 to whatever number you pass in. The calling procedure will pass in 1 in both cases. The question is, what value will your calling procedure see in its variable should the called procedure fail after adding 1 to the input parameter? NOTICE IN PARTICULAR that each of the called procedures fails with an error, and that the calling procedure traps the error and shows you the value of the variable you passed to the called procedure. See how when you pass BY VALUE, your original value is protected from changes made by the failed procedure but when pass BY REFERENCE (eg. NOCOPY) it is not.

create or replace procedure kev_normal (anumber_p in out integer)
as
begin
   anumber_p := anumber_p+1;
   raise zero_divide;
end;
/
show errors

create or replace procedure kev_nocopy(anumber_p in out nocopy integer)
as
begin
   anumber_p := anumber_p+1;
   raise zero_divide;
end;
/
show errors

set serveroutput on

create or replace procedure kevp1
as
   myvar integer;
begin
   myvar := 1;
   dbms_output.put_line('start myvar='||myvar);
   begin
      kev_normal (myvar);
   exception when others then
      dbms_output.put_line('normal myvar='||myvar);
   end;
--
-- my var is still 1 at this point so let us pass it using NOCOPY
--
   begin
      kev_nocopy (myvar);
   exception when others then
      dbms_output.put_line('nocopy myvar='||myvar);
   end;
end;
/
show errors

exec kevp1

23:22:57 SQL> exec kevp1
start myvar=1
normal myvar=1
nocopy myvar=2

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.01


Does this do it for you? Kevin
Re: NO COPY parameters [message #634501 is a reply to message #634499] Tue, 10 March 2015 22:41 Go to previous messageGo to next message
Barbara Boehmer
Messages: 9090
Registered: November 2002
Location: California, USA
Senior Member
It is standard practice to use NOCOPY in a procedure that is used in a user_datastore that is used as an Oracle Context index parameter. This is the only time that I have had occasion to use it.
Re: NO COPY parameters [message #634603 is a reply to message #634501] Wed, 11 March 2015 20:33 Go to previous message
Kevin Meade
Messages: 2103
Registered: December 1999
Location: Connecticut USA
Senior Member
Here is what Barbara is referring too. Far out.
Previous Topic: String Compress
Next Topic: Dynamic SQL - How to convert a varchar2 variable to use as a column name in a select statement
Goto Forum:
  


Current Time: Tue Apr 23 11:10:36 CDT 2024