달력

32024  이전 다음

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

[원문] http://psoug.org/reference/undocumented.html


CREATE TABLE t (
col1 VARCHAR2(5),
col2 VARCHAR2(20));

INSERT INTO t VALUES (111, 'This');
INSERT INTO t VALUES (111, 'is');
INSERT INTO t VALUES (111, 'a');
INSERT INTO t VALUES (111, 'test');
INSERT INTO t VALUES (222, 'This is not');

SELECT * FROM t;

col concat format a40

SELECT col1, wmsys.wm_concat(col2) CONCAT
FROM t
GROUP BY col1;

SELECT col1, TRANSLATE(wmsys.wm_concat(col2), 'A,', 'A ') CONCAT
FROM t

GROUP BY col1; 


'SQL > Oracle' 카테고리의 다른 글

CentOS Linux 에 오라클 설치.  (5) 2009.04.14
간단하게 테스트 해본 오라클 DBMS_JOB 테스트  (0) 2009.04.09
[펌] how to using oracle dbms_job ...  (0) 2009.04.09
[펌] 오라클 패키지  (0) 2009.04.09
오라클 sql developer  (0) 2007.02.08
Posted by tornado
|
  • 오라클 서버

    오라클 서버를 설치하기 위해서는 리눅스 서버를 새로 구축한다.

     

    • Linux Server 신규 구축

      리눅스 서버는 위의 VirtualBox 만드는 과정을 통해 순수하게 리눅스만 설치한다.

      파티션은 아래와 같이 나눈다.

       

파티션

용량

Swap

2GB

/

나머지 용량 전부(여유있게 20GB 잡을것)

 

 

  • 방화벽 설정

    SELinux 는 Disable 시키고 작업한다

    콘솔에서 아래의 명령을 실행 후 그림과 같이 한다.

# setup

 

Firewall configuration 으로 이동 후 엔터(탭 키를 누른다)

 

 

Security Level 을 Disable 시킨 후 탭을 이동하여 OK 한다.

다시 Quit 을 선택하여 종료한다.

 

  • 오라클 다운로드

     

    다운로드 링크 :

    http://www.oracle.com/technology/software/products/database/index.html

     

    위 주소에서 Oracle Database 10g Release 2 (10.2.0.1.0) for Linux x86 를 다운로드

    한다(회원 인증 필요함)

    다운로드 후 /oracle10g 디렉토리에 압축을 해제한다.

    ZIP 파일일 경우 아래와 같이 압축을 해제한다.

# unzip 10201_database_linux32.zip

# mkdir /oracle10g

# mv database /oracle10g

 

  • 오라클 설치를 위한 환경 설정 및 설치
    • /etc/redhat-release 파일 수정하기.

      Vi 에디터로 /etc/redhat-release 파일의 내용을 아래와 같이 고친다.

       

# vi /etc/redhat-release

 

기존 내용

 

 

 

 

바뀐 내용

- Cent OS 는 레드햇 리눅스의 변종(?) 이므로 레드햇으로 수정해야 오라클이 설치된다.

 

  • /etc/security/limits.conf 파일 수정

    위 파일을 vi 에디터로 열고 제일 하단에 아래의 내용을 추가한다.

     

* soft nproc 2047

* hard nproc 16384

* soft nofile 1024

* hard nofile 65536

 

  • /etc/sysctl.conf 파일 수정

    Vi 에디터로 파일을 열고 아래와 같이 수정한다.

    제일 아래의 ########## 아래의 내용은 신규 추가한다.

     

# Kernel sysctl configuration file for Red Hat Linux

#

# For binary values, 0 is disabled, 1 is enabled. See sysctl(8) and

# sysctl.conf(5) for more details.

 

# Controls IP packet forwarding

net.ipv4.ip_forward = 0

 

# Controls source route verification

net.ipv4.conf.default.rp_filter = 1

 

# Do not accept source routing

net.ipv4.conf.default.accept_source_route = 0

 

# Controls the System Request debugging functionality of the kernel

kernel.sysrq = 0

 

# Controls whether core dumps will append the PID to the core filename

# Useful for debugging multi-threaded applications

kernel.core_uses_pid = 1

 

# Controls the use of TCP syncookies

net.ipv4.tcp_syncookies = 1

 

# Controls the maximum size of a message, in bytes

kernel.msgmnb = 65536

 

# Controls the default maxmimum size of a mesage queue

kernel.msgmax = 65536

 

# Controls the maximum shared segment size, in bytes

kernel.shmmax = 4294967295

 

# Controls the maximum number of shared memory segments, in pages

kernel.shmall = 268435456

 

####################

kernel.shmmni = 4096

kernel.sem = 250 32000 100 128

fs.file-max = 65536

net.ipv4.ip_local_port_range = 1024 65000

net.core.rmem_default=262144

net.core.rmem_max=262144

net.core.wmem_default=262144

net.core.wmem_max=262144

 

수정 후 아래의 명령을 실행하여 오류가 있는지 체크(설정 내용이 올바로 출력되면 OK)

/sbin/sysctl -p

 

 

  • /etc/pam.d/login 파일 수정

    Vi 에디터로 오픈하여 아래의 내용을 하단에 추가.

session        required    /lib/security/pam_limits.so

 

  • 설치에 필요한 필수 파일을 yum 으로 업데이트 한다.

    아래의 명령으로 설치에 필요한 필수 파일을 업데이트 한다. 네트워크가 반드시 연결 되어 있어야 한다.

yum -y install make setarch glibc* libaio cpp compat* gcc libXp openmotif elfutils-libelf* unixODBC* sysstat binutils

 

  • 오라클 설치 계정 추가

# groupadd oinstall    // oinstall 그룹 추가

# groupadd dba     // dba 그룹 추가

# useradd -g oinstall -G dba oracle    // oracle 계정을 oinstall 그룹에 -m -g 옵션으로 추가, 동시에 dba 그룹에 -G 옵션으로 추가

# passwd oracle // 비밀번호 지정(111111)

 

  • 오라클 설치 디렉토리 생성

# mkdir -p /u01/app/oracle/product/10.2.0/db_1

# chown -R oracle.oinstall /u01

# mkdir -p /u02/oradata

# chown -R oracle.oinstall /u02

 

  • /hosts 파일 수정

# Do not remove the following line, or various programs

# that require network functionality will fail.

127.0.0.1 localhost

IP주소 ccu_oracle

 

  • /etc/sysconfig/network 리눅스 호스트 이름 변경

    vi 에디터로 오픈하여 HOSTNAME 부분을 변경한다

NETWORKING=yes

NETWORKING_IPV6=no

HOSTNAME=ccu_oracle

 

  • 오라클 사용자 계정 환경변수 설정

# su – oracle

$ cd ~

$ vi .bash_profile

 

아래의 내용을 파일 하단에 추가한다.

TMP=/tmp; export TMP

TMPDIR=$TMP; export TMPDIR

ORACLE_BASE=/u01/app/oracle; export ORACLE_BASE

ORACLE_HOME=$ORACLE_BASE/product/10.2.0/db_1; export ORACLE_HOME

ORACLE_SID=orcl; export ORACLE_SID

ORACLE_TERM=xterm; export ORACLE_TERM

PATH=/usr/sbin:$PATH; export PATH

PATH=$ORACLE_HOME/bin:$PATH; export PATH

export DISPLAY=:0.0

export LANG=C

 

수정이 다 되었다면 저장 후 아래의 명령을 실행하여 적용시킨다.

$ source .bash_profile

        

        위 설정이 다 완료 되었다면 시스템을 한번 리부팅 해준다.        

# shutdown –r now

 

  • 오라클 설치

    주의 : 반드시 oracle 계정으로 설치해야 한다.

     

    오라클 압축 해제 디렉토리(/oracle10g/database) 로 이동하여 runInstaller 를 실행한다.

     

# xhost + ß 반드시 루트 권한에서 실행해야 함

# su – oracle

$ cd /oracle10g/database

$ ./runInstaller

 

오라클 인스톨러 화면

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

오라클 설치중 화면

 

 

 

 

데이터베이스 생성 화면

 

데이터베이스 생성 완료 화면.

 

 

 

 

 

설치가 거의 완료 되면 아래와 같이 ROOT 권한으로 실행할 파일을 알리는 창이 뜬다. 새로운 터미널을 열어서 root 권한으로 해당 스크립트를 실행한다.

# cd /u01/app/oracle/oraInventory/

# ./orainstRoot.sh

# cd /u01/app/oracle/product/10.2.0/db_1/

# ./root.sh ß 이 명령 실행 후 local bin 디렉토리를 묻는데 기본값으로 하면 된다.

 

 

  • 오라클 구동 및 상태보기.

오라클의 구동 및 설정은 oracle 유저로 해야 한다.

 

  • 오라클 상태 보기

# su – oracle

$ lsnrctl status

 

오라클 SID 는 orcl 로 설정하였으며, orcl 리스너가 ready 상태이여야 한다.

 

  • 오라클 리스너 시작/종료

     

리스너 시작

$ lsnrctl start

리스너 종료

$ lsnrctl stop

리스너 상태보기

$ lsnrctl status

 

 

 

 

 

 

 

 

 

 

 

 

  • 오라클 데이터베이스 구동

# su – oracle

$ sqlplus /nolog

SQL> connect sys/password as sysdba

SQL> startup

 

 

  • 오라클 emctl 시작(오라클 엔터프라이즈 매니저)

$ emctl start dbconsole

 


웹브라우저 에서 http://localhost:1158/em/console/aboutApplication 를 오픈하여 엔터프라이즈 매니저로 접근 되는지 확인.

 

아이디 패스워드는 sys/password 이다.

 

 

 

Posted by tornado
|

QUARTS 로 했었는데... 이것도 편하군.

###################################################################
--- 테이블 생성

CREATE TABLE TB_TEST
(
 ID VARCHAR(10),
 NAME VARCHAR(10)
);


--- 패키지 헤더 생성

CREATE OR REPLACE PACKAGE PKG_TORNADO

AS

PROCEDURE UP_TEST_INSERT (v_id IN TB_TEST.ID%type, v_name IN TB_TEST.NAME%type);

END;
/


--- 패키지 바디 생성

CREATE OR REPLACE PACKAGE BODY PKG_TORNADO
AS
PROCEDURE UP_TEST_INSERT
(
 v_id IN TB_TEST.ID%type,
 v_name IN TB_TEST.NAME%type
)
IS

BEGIN

 INSERT INTO TB_TEST (ID, NAME)
 VALUES (v_id, v_name );

 commit;
END;

END;
/


--- ORACLE JOB 생성


VAR JOBNO NUMBER;
BEGIN
DBMS_JOB.SUBMIT 
(:JOBNO
,'PKG_TORNADO.UP_TEST_INSERT(''HEESUNG'', ''TORNADO'');'
,SYSDATE
,'SYSDATE + 1');
COMMIT WORK;
END;
/

 

-- JOBNO 확인

PRINT JOBNO

     JOBNO
----------
        21

-- USER_JOBS 상세 확인

SELECT JOB, LAST_DATE, NEXT_DATE, BROKEN, WHAT FROM USER_JOBS;

       JOB LAST_DATE NEXT_DATE B
---------- --------- --------- -
        21           09-APR-09 N


-- JOB 시작

EXEC DBMS_JOB.RUN(21);

-- JOB 수행 결과 보기.

SELECT * FROM TB_TEST

 


 

'SQL > Oracle' 카테고리의 다른 글

[오라클] 세로열을 가로로 콤마 붙여서 출력.  (0) 2014.10.15
CentOS Linux 에 오라클 설치.  (5) 2009.04.14
[펌] how to using oracle dbms_job ...  (0) 2009.04.09
[펌] 오라클 패키지  (0) 2009.04.09
오라클 sql developer  (0) 2007.02.08
Posted by tornado
|

[출처] http://docstore.mik.ua/orelly/oracle/bipack/ch13_04.htm




13.4 DBMS_JOB Examples

The DBMS_JOB package has all kinds of useful applications waiting to be discovered. DBAs can schedule jobs that look for problem conditions in the database or track and record resource utilization. Developers can schedule large batch operations at off hours without requiring operator intervention.

13.4.1 Tracking Space in Tablespaces

I decided to implement a very simple tracking system that can be used to track the growth of data in tablespaces. Such a system could be used for capacity planning or to trigger an alert of impending space problems.

The system consists of a table called db_space, a view called tbs_space, and a procedure called space_logger. Here is the source code for the system:

/* Filename on companion disk: job6.sql */*
CREATE TABLE db_space
   (tablespace_name   VARCHAR(30)  NOT NULL
   ,calc_date      DATE    NOT NULL
   ,total_bytes    NUMBER  NOT NULL
   ,free_bytes     NUMBER  NOT NULL);

CREATE OR REPLACE VIEW tbs_space
   (tablespace_name
   ,total_bytes
   ,free_bytes)
AS
   SELECT  DF.tbsname         tablespace_name
          ,DF.totbytes        total_bytes
          ,FS.freebytes       free_bytes
     FROM 
          (SELECT  tablespace_name     tbsname
                  ,SUM(bytes)          totbytes
             FROM  dba_data_files
            GROUP BY tablespace_name
          ) DF
         ,(SELECT  tablespace_name     tbsname
                  ,SUM(bytes)          freebytes
             FROM  dba_free_space
            GROUP BY tablespace_name
          ) FS
    WHERE
          DF.tbsname = FS.tbsname;


CREATE OR REPLACE PROCEDURE space_logger
AS
   /*
   || records total size and free space for all
   || tablespaces in table db_space
   ||
   || Author:  John Beresniewicz, Savant Corp
   ||
   || 01/26/98: created
   ||
   || Compilation requirements:
   ||
   || SELECT on TBS_SPACE view
   || INSERT on DB_SPACE table
   */
   CURSOR tbs_space_cur
   IS
   SELECT tablespace_name, total_bytes, free_bytes
     FROM tbs_space;
     
BEGIN
   FOR tbs_space_rec IN tbs_space_cur
   LOOP
      INSERT INTO db_space VALUES
         (tbs_space_rec.tablespace_name
         ,SYSDATE
         ,tbs_space_rec.total_bytes
         ,tbs_space_rec.free_bytes);
   END LOOP;
   COMMIT;
END space_logger;

To set the system in motion, the space_logger procedure can be submitted to the job queue for regular execution as follows:

DECLARE
   jobno   NUMBER;
BEGIN
   DBMS_JOB.SUBMIT
      (job  => jobno
      ,what => 'begin space_logger; end;'
      ,next_date => SYSDATE
      ,interval  => 'SYSDATE+1/24');
   COMMIT;
END;
/

Each time space_logger executes, it records total space, free space, tablespace name, and a timestamp for each tablespace in the database. Adjusting the interval parameter for the job adjusts the frequency of data collection.

13.4.2 Fixing Broken Jobs Automatically

Charles Dye recommended the next example, probably based on his experiences with replication. When jobs have relatively complex execution requirements in terms of the database objects on which they depend, they can easily become broken by incurring multiple execution failures. Perhaps the DBA has modified some database links or recreated tables or views, and the job's definition has been temporarily compromised. Well, it's a pain to manually reset the broken flag for these "not really broken" jobs, so why not have a job that regularly tries to unbreak jobs? Sounds good to me; here is a procedure called job_fixer to do just that:

/* Filename on companion disk: job5.sql */*
CREATE OR REPLACE PROCEDURE job_fixer
AS
   /*
   || calls DBMS_JOB.BROKEN to try and set
   || any broken jobs to unbroken
   */
   
   /* cursor selects user's broken jobs */
   CURSOR broken_jobs_cur
   IS
   SELECT job
     FROM user_jobs
    WHERE broken = 'Y';
    
BEGIN
   FOR job_rec IN broken_jobs_cur
   LOOP
      DBMS_JOB.BROKEN(job_rec.job,FALSE);
   END LOOP;
END job_fixer;

The job_fixer procedure works only on a user's own jobs, so each user submitting jobs to the queue will need a separate job_fixer in the queue.

13.4.3 Self-Modifying and Self-Aware Jobs

The ability to reference the job, next_date, and broken parameters in the job definition allows the procedure executed to alter its own job characteristics. Thus, a job could remove itself from the job queue, or assign its own next execution date based on some criteria decided at runtime by the procedure itself. I've written a small skeleton procedure that demonstrates this capability. It is called smart_job, and makes use of all three of the referenceable parameters when submitted as a job.

When submitted to the job queue, smart_job uses the job definition parameters to modify itself in the following ways:

  • Reschedules itself to parm1_IN minutes after finishing if parm2_IN = "RESTART"

  • Sets next_date NULL causing automatic removal from queue if parm2_IN != "RESTART"

  • Flags itself as broken if any exceptions are encountered

  • Uses the job number to raise an exception

Pay close attention to how the smart_job procedure modifies itself. It uses the fact that the next_date and broken parameters support both IN and OUT modes when referenced by the job definition. Thus, when the broken_out parameter of smart_job has the broken parameter assigned to it in the call to DBMS_JOB.SUBMIT, the value set for broken_out by the procedure gets set for the job by the job queue when the job completes. In this way, smart_job changes its job characteristics without calling any DBMS_JOB procedures.

Here is the source code for smart_job:

/* Filename on companion disk: job4.sql */*
PROCEDURE smart_job
   (parm1_IN IN INTEGER
   ,parm2_IN IN VARCHAR2
   ,next_date_OUT IN OUT DATE
   ,broken_OUT IN OUT BOOLEAN
   ,job_IN IN INTEGER := -1)
IS
   /* declare an exception for testing */
   JOB_LESSTHAN_100  EXCEPTION;

BEGIN
   /* 
   || Do the procedure main line functions
   */
   null;

   /* 
   || use job_IN to branch to exception handler
   || for testing self-breaking
   */
   IF job_IN < 100
   THEN 
      RAISE JOB_LESSTHAN_100;
   END IF;

   /*
   || After main processing is finished, job decides
   || if it should re-execute and determines its own
   || next execution date by adding parm1_IN minutes to 
   || the current time
   */
   IF parm2_IN = 'RESTART'
   THEN
      next_date_OUT := SYSDATE + parm1_IN/1440;
   ELSE
      /* 
      || NULL next_date will cause automatic removal of
      || job from queue
      */
      next_date_OUT := NULL;
   END IF;

EXCEPTION
   /* 
   || job "breaks" itself if unexpected error occurs
   */
   WHEN OTHERS
   THEN
      broken_OUT := TRUE;

END smart_job;

The following test script exercises smart_job:

/* Filename on companion disk: job4.sql */*
var jobno NUMBER
BEGIN
   /*
   || Test the ability to modify next_date.
   */
   DBMS_JOB.SUBMIT
      (:jobno
      ,'smart_job(180,''RESTART'',next_date,broken,job);'
      ,SYSDATE + 1/1440
      ,'SYSDATE + 1');

   COMMIT WORK;
END;
/
print jobno

BEGIN
   /*
   || Test the ability to autoremove
   */
   DBMS_JOB.SUBMIT
      (:jobno
      ,'smart_job(180,''NO_RESTART'',next_date,broken,job);'
      ,SYSDATE + 1/1440
      ,'SYSDATE + 1');

   COMMIT WORK;
END;
/
print jobno

BEGIN
   /*
   || Test the ability to break itself.
   */
   DBMS_JOB.ISUBMIT
      (99
      ,'smart_job(180,''RESTART'',next_date,broken,job);'
      ,SYSDATE + 1/1440
      ,'SYSDATE + 1');

   COMMIT WORK;
END;
/

After executing the test script in SQL*Plus, the following jobs are in the queue:

SQL> SELECT job,last_date,next_date,broken FROM user_jobs;


JOB       LAST_DATE           NEXT_DATE           B
--------- ------------------- ------------------- -
      307                     1997:11:25:11:50:39 N
      308                     1997:11:25:11:50:39 N
       99                     1997:11:25:11:50:40 N

A few minutes later, the job queue looks like this:

SQL> SELECT job,last_date,next_date,broken FROM user_jobs;

JOB       LAST_DATE           NEXT_DATE           B
--------- ------------------- ------------------- -
      307 1997:11:25:11:50:42 1997:11:25:14:50:42 N
       99 1997:11:25:11:50:42 1997:11:26:11:50:42 Y

The tests worked! Job 308 ran once and was removed from the queue for having a NULL next_date. Job 307 ran and rescheduled itself three hours later, which is different from the interval specified in the call to DBMS_JOB.SUBMIT. Finally, job 99 set itself to broken status because its job number was less than 100.

Posted by tornado
|

(펌)http://cafe202.daum.net/_c21_/bbs_search_read?grpid=zchT&fldid=EchX&contentval=00005zzzzzzzzzzzzzzzzzzzzzzzzz&nenc=8SNCt.UzXo8cFfsmTecuug00&dataid=5&fenc=5TjRNwaVVNk0


여기서 설명할 것은 패키지하는 방법과 사용법이다.
일반적으로 그냥 프로시저만을 사용하는 경우가 많으나(나도 그렇지만..), 패키지하여 사용하는 것이
여러 부분에서 우월하므로 왠만하면 패키지화하는 습관을 들이는 것이 좋겠다. 뒷부분에 설명하겠다.


함수의 생성과 사용
프로시저는 뭐고 함수는 또 뭔가?
함수는 리턴값이 있고, 프로시저는 없다. 사실 프로시저도 리턴값을 패러미터로 받을 순 있다.
C언어에서의 call by reference정도로 생각하면 되겠다.

현재시간을 알아보게 싶게 2002-9-19과 같이 리턴하는 함수를 만들어 보자.

SQL> create or replace function print_date return varchar is
  2   cur_date varchar(15);
  3  begin
  4   select to_char(sysdate, 'YYYY-MM-DD') into cur_date from dual;
  5   return cur_date;
  6  end print_date;
  7  /

함수가 생성되었습니다.

SQL> select print_date() from dual;

PRINT_DATE()
-------------------------------------
2002-09-19


함수는 위와 같이 사용하면 되겠다. 별다른 설명은 필요없으리라 본다.
그럼 프로시저를 보자.


프로시저의 생성과 사용
test라는 테이블에 데이터를 insert하는 프로시저를 생성하자.
프로시저는 insert, update, delete등에 사용하면 적절하겠다.

SQL> create table test
  2  (id varchar(10), name varchar(10));

테이블이 생성되었습니다.

SQL> create or replace procedure insert_test
  2  (
  3   v_id    IN TEST.ID%type,  -- ID
  4   v_name  IN TEST.NAME%type  -- 이름
  5  )
  6  is
  7  begin
  8   insert into test(id, name) values(v_id, v_name);
  9   commit;
10  end;
11  /

프로시저가 생성되었습니다.

SQL> exec insert_test('maddog', '강명규');

PL/SQL 처리가 정상적으로 완료되었습니다.

SQL> select * from test;

ID         NAME
---------- ----------
maddog     강명규

SQL> rollback;

롤백이 완료되었습니다.

SQL> select * from test;

선택된 레코드가 없습니다.

SQL>

데이터입력값의 유효성체크와 이에 따른 commit,rollback등 에러처리 추가해 주면 더욱 좋을 것이다.
전체 테이블컬럼을 참조한다면 위의 type대신 rowtype을 사용하는 것도 고려해볼만 하겠다.
예제라 간단하게 했는데, 부족함을 느낀다면 .. 음.. 스스로 하도록 하자.


패키지의 사용
위에서 만든 함수와 프로시저를 하나의 패키지에 담도록 하자.
사실 관련있는 놈들끼리 패키지화 해야 하는데.. 어디까지나 예제이므로 그냥 해 보겠다.

SQL> create or replace package pkg_dbakorea
  2  as
  3  procedure insert_test(v_id IN TEST.ID%type, v_name IN TEST.NAME%type);
  4  function print_date return varchar;
  5  end;
  6  /

패키지가 생성되었습니다.

SQL> create or replace package body pkg_dbakorea
  2  as
  3   procedure insert_test
  4   (                                               
  5    v_id    IN TEST.ID%type,  -- ID                
  6    v_name  IN TEST.NAME%type  -- 이름             
  7   )                                               
  8   is                                              
  9   begin                                           
10    insert into test(id, name) values(v_id, v_name);
11    commit;                                        
12   end;                                            
13  
14   function print_date return varchar is
15    cur_date varchar(15);                                        
16   begin                                                         
17    select to_char(sysdate, 'YYYY-MM-DD') into cur_date from dual;
18    return cur_date;                                             
19   end print_date;                                               
20 
21  end;
22  /

패키지 본체가 생성되었습니다.

그럼, 생성된 패키지내의 프로시저와 함수를 어떻게 사용하는지 보자.

SQL> exec pkg_dbakorea.insert_test('dbakorea','강명규');

PL/SQL 처리가 정상적으로 완료되었습니다.

SQL> select * from test;

ID         NAME
---------- ----------
maddog     강명규
dbakorea   강명규

SQL> select pkg_dbakorea.print_date() from dual;

PKG_DBAKOREA.PRINT_DATE()
---------------------------------------------------
2002-09-26

SQL>




오라클 매거진 영문판 2002 1월/2월호를 참고했습니다.

프로시저에 비해 패키지가 왜 우월한가 의문을 가지고 따질 사람이 있을 수 있으므로 함 따져보자.

모듈화
애플리케이션 디자인 용이함
Information Hiding
추가된 기능성
더 좋은 성능


프로시저A는 프로시저B를 호출하는 코드를 가진다고 하자.
그런데 프로시저B의 코드가 변경되면 어떻게 되는가?
프로시저A는 프로시저B의 변경에 영향을 받으므로 재컴파일되어야 한다. 귀찮겠다.
그럼, 패키지를 사용하면 어떻길래? 따지냐.. --; 이주일씨의 명복을 빕니다.

프로시저A를 포함한 패키지PKG_A와 프로시저B를 가진 패키지PKG_B가 있고
PKG_A는 PKG_B의 스펙에 대한 의존성을 가진다고 하자.
이 경우에서, PKG_B의 스펙이나 인터페이스에 대한 변경이 아니라면 PKG_B의 BODY는 PKG_A에 상관없이 변경될 수 있다.

SQL> create or replace procedure B
  2  as
  3  begin
  4   null;
  5  end;
  6  /

프로시저가 생성되었습니다.

SQL> create or replace procedure A
  2  as
  3  begin
  4   B;
  5  end;
  6  /

프로시저가 생성되었습니다.

SQL>


위에서 보듯, 프로시저A는 프로시저B를 호출하고 있다. 즉, 의존성을 가지고 있겠다.
당연히, 프로시저B를 먼저 생성한 다음 프로시저A를 생성해야 한다. 반대로 해볼까?


SQL> drop procedure B;

프로시저가 삭제되었습니다.

SQL> drop procedure A;

프로시저가 삭제되었습니다.

SQL> create or replace procedure A
  2  as
  3  begin
  4   B;
  5  end;
  6  /

경고: 프로시저 생성시 컴파일 오류가 발생했습니다.

SQL> drop procedure a;

프로시저가 삭제되었습니다.

SQL>


위에서 보듯이 안된다.
그럼.. 무엇을 말하려고? 음.. 패키지는 그렇지 않다는 것이다.


SQL> create or replace package pkg_a
  2  as
  3   procedure a;
  4  end;
  5  /

패키지가 생성되었습니다.

SQL> create or replace package pkg_b
  2  as
  3   procedure b;
  4  end;
  5  /

패키지가 생성되었습니다.

SQL>


위에서 패키지에 대한 스펙을 생성했다.
스펙의 생성순서는 상관이 없고 서로 의존성도 가지지 않는다.
그럼 패키지 body를 생성해 보자.

SQL> create or replace package body pkg_a
  2  as
  3   procedure a
  4   is
  5   begin
  6    pkg_b.b;
  7   end;
  8  end;
  9  /

패키지 본체가 생성되었습니다.

SQL> create or replace package body pkg_b
  2  as
  3   procedure b
  4   is
  5   begin
  6    null;
  7   end;
  8  end;
  9  /

패키지 본체가 생성되었습니다.


설명 필요없겠다. 위에서 보듯 생성순서는 상관이 없다.
패키지A에 있는 프로시저A는 패키지B의 프로시저B를 호출하고 있지만,
이 시점에서 패키지B의 프로시저B는 존재하지 않는다. 하지만, 상관없다는 것을 알 수 있다.
다시 말하면, 패키지의 스펙에 의존하지만, 패키지의 body에는 의존하지 않음을 알 수 있다.


SQL> col object_type format a15
SQL> col object_name format a10
SQL> col status format a10
SQL> select object_type, object_name, status
  2  from user_objects
  3  where status = 'INVALID'
  4  order by object_type, object_name;

선택된 레코드가 없습니다.

SQL>


그럼 실제 프로시저와 패키지가 변경해서 위에서 말한 내용이 사실인지 확인해 보자.


SQL> create or replace procedure B
  2  as
  3  begin
  4   null;
  5  end;
  6  /

프로시저가 생성되었습니다.

SQL> create or replace procedure A
  2  as
  3  begin
  4   B;
  5  end;
  6  /

프로시저가 생성되었습니다.

SQL> create or replace procedure b
  2  as
  3  begin
  4   null;
  5  end;
  6  /

프로시저가 생성되었습니다.

SQL> select object_type, object_name, status
  2  from user_objects
  3  where status = 'INVALID'
  4  order by object_type, object_name;

OBJECT_TYPE     OBJECT_NAM STATUS
--------------- ---------- ----------
PROCEDURE       A          INVALID

SQL> create or replace package body pkg_b
  2  as
  3   procedure b
  4   is
  5   begin
  6    null;
  7   end;
  8  end;
  9  /

패키지 본체가 생성되었습니다.

SQL> select object_type, object_name, status
  2  from user_objects
  3  where status = 'INVALID'
  4  order by object_type, object_name;

OBJECT_TYPE     OBJECT_NAM STATUS
--------------- ---------- ----------
PROCEDURE       A          INVALID

SQL>

위에서 보듯이 프로시저는 변경에 대해 민감하고(?), 패키지는 둔하다.
고로 패키지가 더 flexible하다 할 수 있겠다.
Posted by tornado
|
Posted by tornado
|