본문 바로가기

Database/PLSQL

068 - [Oracle PL/SQL] NOCOPY

 

We use NOCOPY in complexe data types (LOBs, XMLTYPEs, collections etc.)

여기서 레퍼런스에 의한 전달과 값에 의한 전달의 차이를 알아보자

 

 

  • IN parameter always passed by reference, IN 파라미터는 항상 레퍼런스에 의한 전달이다

 

 

 

  • OUT/IN OUT parameters can be passed

1-Pass By Value ( default), 파라미터의 사이즈가 작다면 문제가 없지만 크다면 복사하는 과정에서 많은 부하가 발생한다.

값의 전달은, 오류가 발생할때, 프로시져에 전달한 값이 무엇인지 알고 롤백을 할때도 값을 유지한다.

 

 

 

2-Pass By Reference using no copy, 복사 과정이 일어나지 않아서 실행

오류가 발생하면, 입력값(여기서는 x=10)을 유지할 수 없으므로 예외처리를 반드시 해야한다.

 

 

 

 

 

 

 

각 상황에 따른 샘플코드는 아래와 같다.

 

  • IN parameter
# 1. IN parameter always passed by reference

create or replace procedure pass_by_ref
( p_id in number ) --p_id called formal parameter
is
begin
--p_id :=555; --this is not valid
dbms_output.put_line(p_id);
end;

execute pass_by_ref (10); 
--------------------------------
10


# 위의 주석 부분을 제거하고 파라미터는 프로시져 내부에서 직접 접근하면 오류가 발생한다.

create or replace procedure pass_by_ref
( p_id in number ) --p_id called formal parameter
is
begin
--p_id :=555; --this is not valid
dbms_output.put_line(p_id);
end;
--------------------------------
LINE/COL  ERROR
--------- -------------------------------------------------------------
5/1       PL/SQL: Statement ignored
5/1       PLS-00363: expression 'P_ID' cannot be used as an assignment target
Errors: check compiler log

 

 

 

  • OUT/IN OUT parameters can be passed, Pass By Value ( default) 
/*
	Pass By Value : The default action is to create a temporary buffer (formal parameter), 
	copy the data from the parameter variable (actual parameter) to that buffer and work 
	on the temporary buffer during the lifetime of the procedure. 
	On successful completion of the procedure, 
	the contents of the temporary buffer are copied back into the parameter variable. 
	In the event of an exception occurring, the copy back operation does not happen.
*/
create or replace procedure pass_by_value1
    ( P_id IN out number)
is
begin
    P_id:=P_id*10;
      if P_id>100 then
      	raise VALUE_ERROR;
      end if;
end;



# v에 5를 입력하여 예외처리가 발생하지 않게 실행한다. 결과는 50이다.
declare
    v number:=5;---try first 5 then 20
begin
    pass_by_value1(V);
    dbms_output.put_line('NO ISSUE '||v);

    EXCEPTION
        WHEN VALUE_ERROR THEN 
        dbms_output.put_line('EXCEPTION '||v);
end;
---------------------------------------------
NO ISSUE 50
# 정상완료되어 결과를 값복사를 통해서 v 값이 변경되었다.


# v에 20를 입력하여 예외처리가 발생하게 실행.
# 오류가 발생하면서 정상완료시 발생하는 값복사가 생기지 않으므로 최초값인 20이 유지된다.
declare
    v number:=20;---try first 5 then 20
begin
    pass_by_value1(V);
    dbms_output.put_line('NO ISSUE '||v);

    EXCEPTION
        WHEN VALUE_ERROR THEN 
        dbms_output.put_line('EXCEPTION '||v);
end;
---------------------------------------------
EXCEPTION 20

 

 

 

  • OUT/IN OUT parameters can be passed, Pass By Reference using no copy
# 같은 코드인데, 옵션인 nocopy 추가한 샘플코드, 레퍼런스를 통한 값 전달

create or replace procedure pass_by_ref
( P_id IN out nocopy number)
is
begin
    P_id:=P_id*10;
    if P_id>100 then
        raise VALUE_ERROR;
    end if;
end;

declare
    v number:=20;
begin
    pass_by_ref(V);
    dbms_output.put_line('NO ISSUE '||v);

    EXCEPTION
        WHEN VALUE_ERROR THEN 
        dbms_output.put_line('EXCEPTION '||v);
end;
---------------------------------------------
EXCEPTION 200

# 이번에는 예외처리가 발생했지만 레퍼런스를 통한 값 전달이므로 초기값이 변경되었다.

 

 

 

 

 

<샘플코드에서 사용한 데이터는 HR 스키마이고, 오라클 설치시 생성할 수 있는 기본 스키마 입니다>