Post List

레이블이 Oracle인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Oracle인 게시물을 표시합니다. 모든 게시물 표시

2025년 6월 25일 수요일

백업의기본

Describe 백업의기본 here


백업....


백업은 데이타베이스 관리자가 하는 일중에 비중이 큰 작업입니다..
왜냐하면 어떤 조직에서 데이타베이스 시스템을 도입하였다면 이는 그 조직이 정보의 중요함을
인식했기 때문입니다...
정보는 곧 힘이 될 수 있습니다...
이렇게 조직에서 중요하게 인식한 정보는 바로 데이타베이스에서 어떤 처리 과정을 거쳐서
나오는 결과물이기 때문입니다...
만약 데이타베이스에 문제가 생긴다면 그 조직의 정보체계에 큰 문제가 일어나고...
또한 경제적인 손실이 만만치 않을 것이기 때문에 만약의 사태에 대비한 백업이 데이타베이스 관리자의 
비중있는 일이 된 것입니다..
이미 위 단원에서 아카이브로그 모드로 전환하는 방법과 부분백업(온라인백업)을 해보았습니다..
이 부분은 이미 해본것이기 때문에 직접해보는 것은 생략하고...
개념과 기초에 대한 야그를 더 해보겠습니다...
물론 다른 종류의 백업도 해볼작정입니다...

==================
아카이브 로그 모드
==================

먼저 아카이브로그 모드에 대해서 살펴보겠습니다..
보통 오라클을 셋업하면 노아카이브 로그모드에서 동작을 시킵니다..(별다른 옵션에 체크를 하지 않으셨다면..)
전에도 언급했듯이 아카이브로그의 의미는 로그파일을 또한번 다시 다른 저장장소에 저장한다는 것입니다...
아카이브 모드를 사용하는지 사용하지 않는지는 백업의 방법과 복구의 방법을 결정지을 수 있는 백업 솔루션이지여..
트랜잭션의 복구가 될 수 있는가 될 수 없는가는 아카이브로그 모드에 따라서 달라지게되는 것입니다..
모든 트랜잭션은 아카이브 로그모드일때 가능합니다...
물론 '안정성'의 측면에서 봤을때는 아주 좋습니다..그러나 '성능'에서 본다면...추가적인 오라클의 작업과 
추가적인 저장장치를 필요로 합니다...
그러므로 전체적인 성능은 약간 저하될 수 있습니다..

전에도 한번 해봤듯이 부분백업  같은 경우에는 반드시 아카이브로그 모드에서만 할 수 있습니다..
이유는 백업도중 어떤 트랜잭션이 발생 할 수 있으므로 백업하는 동안에는 해당 테이블스페이스에 사용자가 
접근하지 못하기 때문에... 데이타의 기록을 할 수 없습니다...
이런 경우는 아카이브 로그를 사용해서 백업도중 발생한 데이타베이스에 대한 변경을 적용해 줄 수 있는 것입니다..
상호 보완적이라도고 볼 수 있겠네여...헐헐~

SQL> select log_mode from v$database;

LOG_MODE
------------
ARCHIVELOG

SQL> select group#, archived from v$log;

    GROUP# ARC
---------- ---
         1 YES
         2 NO
         3 YES

SQL> connect system/manager
연결되었습니다.
SQL> archive log list;
ORA-01031: 권한이 불충분합니다
SQL> connect sys/change_on_install as sysdba
연결되었습니다.

SQL> archive log list;
데이터베이스 로그 모드              아카이브 모드
자동 아카이브             사용
아카이브 대상            /export/home/oracle/8i/oradata/archive
가장 오래된 온라인 로그 순서     4110
아카이브할 다음 로그   4112
현재 로그 순서           4112
SQL> 

아카이브 모드의 설정해제는 ALTER DATABASE NOARCHIVELOG; 문장으로 합니다...
ALTER DATABASE문장은 데이타베이스를 셧다운후 마운트까지만 하고 실행야 합니다...
아카이브에 대한 파라미터 파일에서 LOG_ARCHIVE_FORMET라는 것이 있었습니다..
여기서 설정해주는 값은 다음과 같은 의미를 가지고 있습니다..

%T : 쓰레드 번호   --> arch0000000001 
%t : 쓰레드 번호   --> arch1
%S : 로그 일련번호 --> arch0000000004
%s : 로그 일련번호 --> arch4

%t와 %T는 OPS(오라클 병령 서버)에서 사용하는 쓰레드를 나타냅니다..


SQL> !vi $ORACLE_HOME/dbs/initORCL.ora

                .
                .
                .

log_archive_start = true
log_archive_dest = /export/home/oracle/8i/oradata/archive
log_archive_format = arch%s.arc

                .
                .
                .
                .
아카이브 로그모드를 사용하면 아카이브된 로그는 지정된 저장장치에 계속 쌓이게 됩니다...
이렇게 하면 저장공간이 부족한 상태에 이르게 되는데...이렇게 저장공간이 부족하게 되면 
오라클은 에러를 발생하게 됩니다..
그러므로 어느정도의 아카이브로그가 쌓이게 되면 다른 저장장치로 아카이브된 로그들을 
옮겨줘야 합니다..

유닉스에서는 보통 dd명령을 통해서 아카이브 로그 파일을 다른 저장장치로 옮깁니다..
다음은 그 예입니다..

#dd if = /export/home/oracle/8i/oradata/archive of = /dev/rmt/ctape1

이렇게 운영체제의 명령을 통해서 아카이브 로그를 관리할때는 복구시 빠른 작업을 하기 위해서
아카이브 로그 파일들을 순서에 맞게 잘 정리하는 것도 중요합니다..
백업과 복구에서 중요한 것은 어떤 문제로 인하여 서비스를 가능한 빨리 정상화하는 것이 중요하기 
때문에...문제 발생시 아카이브 로그 파일들을 정리하고...또 필요한 파일들을 찾는데 시간을 허비해서는 안돼기 
때문입니다..



=======================
전체 백업(whole backup)
=======================

저는 처음에 홀백업이라고 해서 홀을 '구멍'이라는 뜻을 받아들였었슴니다..
그래서 전체 데이타베이스에서 일 부분만 백업하는 방법인 줄 알았는데...역쉬 아니더군여...
헐헐~ 
전체 백업은 데이타베이스가 작고, 사용자가 많치 않을때 효율적이고 경제적입니다..
기냥 전체 백업에 들어가도 데이타 파일을 복사하는데 시간이 참 무료하게 느껴질 정도로 오래 걸립니다..
담배한대 태우고..커피 마시고..텔레비젼 조금 보다가 오면 됩니다..

대용량 데이타베이스를 전체 백업하는 것은 좀 무리가 있을 수 도 있습니다...
대용량 데이타베이스는 권하기를 전문회사의 백업관련 제품을 이용하는 것이 좋다구 합니다..
전체데이타베이스 백업은 아주 쉽기도 하고 어렵기도 한 백업 방법입니다...
주의할 점은 백업할때 데이타베이스 셧다운과 스타트 사이에 모든 관련 파일을 복사해야 한다는 것입니다..
띄엄띄엄 받는 백업은 무의미합니다....또한 정상적인 구동중에 운영체제 상에서 관련 파일을 복사하는 것도 
의미가 없습니다...그 이유는 정상적인 가동중에는 트랜잭션이 진행중일 수 있기때문입니다...
 
사용은 간단합니다..

1. 데이타베이스 셧다운
2. 운영체제 명령을 통해서 모든 오라클 데이타베이스(파일들...)을 백업
3. 데이타베이스 스타트업

오라클에게 반드시 필요한 파일은 Datafile, Redo log file, control file, parameterfile입니다.
전체 백업은 반복적이 작업입니다...그러므로 실수도 할 수 있겠지여...이런 실수를 방지하고...업무 효율을 높이기 위해서
쉘스크립트를 작성해서 하는 것이 좋습니다...정기적인 전체 백업이 필요하다면 스케줄러를 써야 겠지여...
잘 작성된 쉘스크립트는 데이타베이스 백업 관리에 아주 큰 도움이 될 것입니다..

다음은 오라클의 파일에 관련된 데이타 사전뷰입니다..

SQL> select file_name from dba_data_files;

FILE_NAME
------------------------------------------------------------------

/export/home/oracle/8i/oradata/ORCL/tools01.dbf
/export/home/oracle/8i/oradata/ORCL/drsys01.dbf
/export/home/oracle/8i/oradata/ORCL/users01.dbf
/export/home/oracle/8i/oradata/ORCL/indx01.dbf
/export/home/oracle/8i/oradata/ORCL/rbs01.dbf
/export/home/oracle/8i/oradata/ORCL/temp01.dbf
/export/home/oracle/8i/oradata/ORCL/system01.dbf
/export/home/oracle/8i/oradata/data1.dbf
/export/home/oracle/8i/oradata/data2_a.dbf
/export/home/oracle/8i/oradata/temp_data.dbf
/export/home/oracle/8i/oradata/data1_1.dbf
/export/home/oracle/8i/oradata/local_manage_data.dbf

12 개의 행이 선택되었습니다.

SQL> select value from v$parameter
  2  where name = 'control_files';

VALUE
-------------------------------------------------------------------------------------------------------------------------------------------------------------
/export/home/oracle/8i/oradata/ORCL/control01.ctl, /export/home/oracle/8i/oradata/ORCL/control02.ctl, /export/home/oracle/8i/oradata/ORCL/control03.ctl


SQL> select member from v$logfile;

MEMBER
--------------------------------------------------------------------------------------
/export/home/oracle/8i/oradata/ORCL/redo03.log
/export/home/oracle/8i/oradata/ORCL/redo02.log
/export/home/oracle/8i/oradata/ORCL/redo01.log

SQL>

SQL> shutdown
데이터베이스가 닫혔습니다.
데이터베이스가 마운트 해제되었습니다.
ORACLE 인스턴스가 종료되었습니다.
SQL> !
yasicom% pwd
/export/home/oracle/8i
yasicom% mkdir backup

######### 운영체제 상에서 관련된 파일들 복사#########

yasicom% cp $ORACLE_HOME/dbs/*.ora $ORACLE_HOME/backup                    
yasicom% cp $ORACLE_HOME/oradata/ORCL/*.dbf $ORACLE_HOME/backup           <------------ 시간이 좀 걸릴수 있음.......
yasicom% cp $ORACLE_HOME/oradata/ORCL/*.ctl $ORACLE_HOME/backup
yasicom% cp $ORACLE_HOME/oradata/ORCL/*.log $ORACLE_HOME/backup
yasicom% exit
yasicom%
SQL> startup
ORACLE 인스턴스가 시작되었습니다.

Total System Global Area   72704160 bytes
Fixed Size                    73888 bytes
Variable Size              55681024 bytes
Database Buffers           16777216 bytes
Redo Buffers                 172032 bytes
데이터베이스가 마운트되었습니다.
데이터베이스가 열렸습니다.

다음은 전체백업의 쉘스크립트를 작성한 것입니다...
이 스크립트를 일정기간동안 주기적으로 실행하려면 운영체제의 스케줄러를 이용합니다..

SQL> !vi $ORACLE_HOME/dbs/whole_backup.sql

#전체백업 스크립트
#데이타베이스 종료

$ORACLE_HOME/bin/sqlplus /nolog << EOF
connect sys/change_on_install as sysdba
shutdown immediate
exit
#
#데이타베이스와 관련된 파일 복사
cp $ORACLE_HOME/dbs/*.ora $ORACLE_HOME/backup
cp $ORACLE_HOME/oradata/ORCL/*.dbf $ORACLE_HOME/backup
cp $ORACLE_HOME/oradata/ORCL/*.ctl $ORACLE_HOME/backup
cp $ORACLE_HOME/oradata/ORCL/*.log $ORACLE_HOME/backup
#
#데이타베이스 시작
$ORACLE_HOME/bin/sqlplus /nolog << EOF
connect sys/change_on_install as sysdba
startup
exit
EOF
~
~
~
~
~
~
~
~
~
:wq


==========================
온라인 백업/ 오프라인 백업 
==========================

이것도 윗 단윈에서 했었지여...아카이브 로그를 수행할때 말입니다...
여기서 말하는 온라인 백업/ 오프라인 백업은 테이블스페이스를 단위로 백업을 하는 것을 의미합니다..
저는 안했지만 오픈 백업에서 중요한 것은 테이블 스페이스단위로 백업 작업을 끝냈으면
컨트롤 파일과 로그 파일도 함께 복사를 해두라는 것입니다..
이것 역시 쉘스크립트를 작성하면 편하겠지여...

다음은 컨트롤 파일에 대한 백업 명령 예입니다..

SQL> ALTER DATABASE BACKUP CONTROLFILE TO '경로.......';

SQL> ALTER DATABASE BACKUP CONTROLFILE TO TRACE;          <---------- *.trc 형태로 파일을 복사합니다..



===============
엑스포트/임포트
===============

엑스포트와 임포트는 exp, imp 명령으로 수행합니다..
엑스포트와 임포트를 이용한 백업 방법을 보통 논리적인 백업이라고 합니다..
논리적이라는 것은 DBMS가 데이타 모델의 분류에서 실행 데이타 모델이라는 것입니다..
즉, 논리적인 관점에서의 백업입니다..논리적인 관점이라는 것은 오라클의 객체들 바라볼때의 관점입니다..
그러니까 엑스포트/임포트는 객체를 백업하고 복구하는 방법이라고 볼수 있습니다...
백업부분인데...보통 임포트와 엑스포트는 같이 붙어다니까...기냥 
백업 단원에서 언급하겠습니다..

특이한 점은 엑스포트와 임포트가 백업/복구 말고도 다른 기능을 수행한다는 것입니다...
다른 기능은 데이타베이스의 객체와 데이타를 서로 이동시키고, 또한 테이블, 인덱등을 재정장 하기 때문에
단편화(Freagmentaion)을 감소시킨다는 것입니다...
아주 유용하죠?

익스포트 옵션을 살펴보게습니다...옵션은 외울필요 없이 그때그때 참고하면서 하면 되겠습니다..
자연스레 외워져 있다면 더 좋겠지여..

USERID/PASSWORD : 사용자명과 패스워드
BUFFER          : 데이타를 읽어오는데 필요한 버퍼크기
                  0으로 설정되면 한번에 한행만 읽어온다.
                  데이타형이 LONG인 것은 한번에 하나의 행만 읽어와야 한다.
FILE            : 백업 파일명
GRANTS          : 백업할 객체의 권한 백업
INDEXS          : 인덱스를 생성할 수 있는 sql문을 파일로 만들어준다.
ROWS            : 테이블의 데이타를 백업해준다.
CONSTRAINTS     : 테이블이 가지고 잇는 제약조건 백업
COMPRESS        : 익스텐트 영역을 하나의 영역으로 압축하여 백업
FULL            : 데이타베이스 전체 백업
OWNER           : 백업할 객체를 가지고 잇는 사용자명 정의
TABLES          : 특정 테이블을 선택하여 백업
INCTYPE         : FULL = Y일때...
                  
                  COMPLETE    : 모든 테이블의 데이타를 백업
                  INCREMENTAL : 최근에 백업(COMPLETE, CUMULATIVE, INCREMENTAL)한 이후의 변경된 테이블만 백업
                  CUMULATIVE  : 최근에 백업(COMPLETE, CUMULATIVE)한 이후의 변경된 

RECORD          : SYS.INCVID, SYS.INCEXP테이블에 INCREMENTAL 익스포트 백업내용을 기록해준다.
HELP            : 도움말
LOG             : 지정한 파일에 로그 내용을 기록해준다.
CONSISTENT      : 백업 진행중인 테이블의 데이타가 변경중이라면 변경전의 데이타를 백업한다.
STATISTICS      : 백업하는 동안 테이블과 인덱스에 있는 통계정보를 수집해 준다.
                  
                  ESTIMATE : 전체 데이타중 일부 데이타로 통계정보를 수집
                  COMPUTE  : 전체 데이타로 통계 정보를 수집한다
                  NONE     : 통계정보를 수집하지 않는다.

DIRECT          : 데이타버퍼 캐쉬 영역을 사용하지 않고 백업하기 때문에 매우 빠르게 백업할 수 있다. 
                  객체타입, 중첩테이블, LOB, REF, VARRAY 타입에는 사용할 수 없다.  
FEEDBACK        : 백업하는 도중에 행의 수마다 점(.)을 찍는다.

엑스포트에서의 백업모드는 아래의 3가지와 같으며 다음과 같은 내용이 백업됩니다..

테이블 모드
   - 테이블 생성 스크립트
   - 테이블 데이타
   - 테이블 권한
   - 인덱스
   - 제약조건
   - 트리거
(예: exp USERID = system/manager FULL = y)

사용자 모드
   - 테이블 생성 스크립트
   - 테이블 데이타
   - 테이블 권한
   - 인덱스
   - 제약조건
   - 트리거
   - 클러스트
   - 스냅샷
   - 저장 프로시저
   - 시노님
   - 뷰 
(예: exp USERID = scott/tiger OWNER = scott)

전체 모드
   - 테이블 생성 스크립트
   - 테이블 데이타
   - 테이블 권한
   - 인덱스
   - 제약조건
   - 트리거
   - 클러스트
   - 스냅샷
   - 저장 프로시저
   - 시노님
   - 뷰 
   - 프로파일
   - 롤
   - 롤백 세그먼트
   - 감사
   - 테이블스페이스 데이타
(예: exp USERID = scott/tiger TABLES = (scott.emp, yasi.test) )
   
   
임포트

그럼 논리적인 백업의 복구 방법인 임포트에 대해서 살펴보겠습니다...
바로 임포트 파라미터로 들어가지여..

USERID       : 접속할 오라클의 사용자명/패스워드  
BUFFER       : 엑스포트와 같다
FILE         : 엑스포트와 같다
SHOW         : Y값으로 설정되면 실제 복구 작업은 실행되지 않고 복구해야할 내역만 화면에 출력
IGONRE       : 이미 존재하는 테이블에 대해 복구작업을 실행하면 'Object already exists'라는 에러가 발생하는데 
               이 에러를 무시하고 계속 복구작업 수행
INDEXES      : 인덱스를 별도로 생성할 것인지 표시
ROWS         : 테이블의 데이타를 복구할 것인지 표시
FULL         : 백업된 모든 데이타를 복구
FROMUSER     : 여기에 정의된 사용자가 가지고 있는 모든 객체를 복구
TOUSER       : 여기에 정의된 사용자가 FROMUSER 리스트에 정의되어 있는 사용자의 모든 객체를 복구
TABLES       : 복구할 테이블을 지정하여 복구 TABLES = (emp, dept)
RECORDLENGTH : 한번에 임포트할 수 있는 파일의 레코드 길이를 정의
INCTYPE      : 복구할 파일의 COMPLETE, CUMULATIVE, INCREMENTAL 유형을 정의
COMMIT       : Y를 설정하면 각 배열을 입력한후 commit문을 실행
HELP         : 도움말
PARFILE      : 임포트 파라미터를 외부 파일에 정의하여 사용하는 경우 파일명 표시
               imp USERID = scott/tiger PARFILE = test.par
LOG          : 모든 에러 메세지를 기록하는 파일명을 표시 
DESTORY      : 데이타베이스에 이미 존재하는 객체를 삭제후 재생성해주며 FROMUSER, TOUSER 옵션과 같이 사용한다.
INDEXFILE    : 엑스포트 파일에 있는 모든 객체를 재생성 할 수 있는 CREATE문과 ALTER문을 외부 파일로 생성해 줍니다..


간단하게 엑스포트/임포트 해보겠습니다..

SQL> !exp userid = scott/tiger file = $ORACLE_HOME/oradata/scott.dmp owner = scott

Export: Release 8.1.7.0.0 - Production on 수 Dec 12 15:29:36 2001

(c) Copyright 2000 Oracle Corporation.  All rights reserved.


접속 대상: Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production
With the Partitioning option
JServer Release 8.1.7.0.0 - Production
KO16KSC5601 문자 설정과 KO16KSC5601 NCHAR 문자 설정에서 엑스포트가 종료되었습니다\
. 스키마 이전 단계의 객체와 작업을 엑스포트합니다\r

. SCOTT 사용자를 위해 외래 함수 라이브러리 이름을 엑스포트합니다 \
. SCOTT 사용자의 객체 유형 정의를 엑스포트 합니다 \r

SCOTT의 객체를 엑스포트하려고 합니다 ...
. 데이터베이스 링크 엑스포트 중
. 순차 번호 엑스포트 중
. 클러스터 정의 엑스포트 중
. SCOTT의 테이블을 엑스포트하려고 합니다 via 규정 경로...
. . 테이블                          BONUS(를)을 엑스포트 중          0 행이 엑스포트됨
. . 테이블                           DEPT(를)을 엑스포트 중          4 행이 엑스포트됨
. . 테이블                            EMP(를)을 엑스포트 중         15 행이 엑스포트됨
. . 테이블                       SALGRADE(를)을 엑스포트 중          5 행이 엑스포트됨
. . 테이블                       SEQ_TEST(를)을 엑스포트 중          1 행이 엑스포트됨
. . 테이블                           TEST(를)을 엑스포트 중          0 행이 엑스포트됨
. 동의어 엑스포트 중
. 뷰 엑스포트 중
. 저장 프로시저 엑스포트 중
. 작업을 엑스포트합니다
. 참조 무결성 제약조건 엑스포트 중
. 트리거 엑스포트 중
. 인덱스유형을 엑스포팅합니다
. 비트맵, 함수, 기능과 확장 가능한 인덱스들을 엑스포트합니다
. 이후 테이블 처리를 엑스포트 중
. 스냅샷 엑스포트 중
. 스냅샷 로그 엑스포트 중
. 작업 대기열을 엑스포트 중
. 리프레쉬 그룹과 자식 엑스포트 중
. 차원을 엑스포트합니다\
. 스키마 이후 단계의 객체와 작업을 엑스포트합니다\r

. 통계를 엑스포트합니다
엑스포트가 경고 없이 정상적으로 종료되었습니다.

SQL> connect system/manager
연결되었습니다.

SQL> drop user scott
  2  cascade;

사용자가 삭제되었습니다.

SQL> create user scott identified by tiger
  2  default tablespace users;

사용자가 생성되었습니다.

SQL> grant connect, resource to scott;

권한이 부여되었습니다.

SQL> !imp userid=scott/tiger file=$ORACLE_HOME/oradata/scott.dmp full=y

Import: Release 8.1.7.0.0 - Production on 수 Dec 12 15:49:48 2001

(c) Copyright 2000 Oracle Corporation.  All rights reserved.


접속 대상: Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production
With the Partitioning option
JServer Release 8.1.7.0.0 - Production

엑스포트 파일은 규정 경로를 거쳐 EXPORT:V08.01.07 에 의해 생성되었습니다
KO16KSC5601 문자집합과 KO16KSC5601 NCHAR 문자 집합에 임포트가 완성되었습니다
. SCOTT 객체를 SCOTT(으)로 임포트하는 중입니다
. . 테이블                        "BONUS"(를)을 임포트 중          0 행이 임포트되었습니다
. . 테이블                         "DEPT"(를)을 임포트 중          4 행이 임포트되었습니다
. . 테이블                          "EMP"(를)을 임포트 중         15 행이 임포트되었습니다
. . 테이블                     "SALGRADE"(를)을 임포트 중          5 행이 임포트되었습니다
. . 테이블                     "SEQ_TEST"(를)을 임포트 중          1 행이 임포트되었습니다
. . 테이블                         "TEST"(를)을 임포트 중          0 행이 임포트되었습니다
사용 가능한 제약 조건에 관해서...
임포트가 경고 없이 정상적으로 종료되었습니다.

SQL> connect scott/tiger
연결되었습니다.
SQL> select * from dept;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON





여기까지 백업에 대한 내용이였습니다...








분석용 함수의 이용

Contents

1 기본 사항
2 Windowing절에 대한 설명
3 활용 예제
4 추가자료



1 기본 사항 #

분석함수는 8i 버전에서 persnal edition, enterprise edition에서 지원하고, 9i버전에서는 모든 버전에 지원된다. 문법은 다음과 같다.


SELECT Analytic_Function ( arguments )
       OVER( [ PARTITION BY 칼럼 ] [ ORDER BY 절 ] [ Windowing 절] )
FROM 테이블 명;

  • Partition By : 전체 집합을 기준에 의해 소그룹으로 나눔
  • Order By : PARTITION BY에 나열된 그룹을 정렬함
  • Windowing : 펑션의 대상이 되는 행 기준으로 범위를 세밀하게 조정 (메뉴얼: window IS a physical or logical SET of rows)


2 Windowing절에 대한 설명 #

RANGE는 값이며, ROWS는 행의 수를 의미한다.
- RANGE BETWEEN 50 PRECEDING AND 150 FOLLOWING
  : BETWEEN Current_Row -50 AND 150 의 파티션 내의 모든행이 window
    즉, Current_Row의 값 - 50 ~ Current_Row의 값 + 150의 값은 모두 하나의 그룹

- ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
  : 현재행을 기준으로 파티션 내의 앞/뒤 한건이 Window

- RANGE UNBOUNDED PRECEDING
  : 현재 행을 기준으로 파티션 내의 첫 번째 행까지가 Window

- ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING     
  : 현재행을 기준으로 파티션 내의 첫 번째 행부터 끝 행까지가 Window. 즉, 파티션 모두가 Window

3 활용 예제 #

요것만 이해하면 분석용 함수는 끝난다.
 sql
               
select
        ename
      , sal
      , sum(sal) over(partition by deptno order by sal) ASC순으로_부서별_sal누적
      , sum(sal) over(partition by deptno) 부서별_sal합계
      , sum(sal) over(order by deptno, sal) deptno_sal_ASC정렬후_누적
      , sum(sal) over() sal총계
from emp
order by deptno, sal;
--over() 안의 oder by는 정렬 후 해당 행과 이전행을 모두 함친 것의 계산 - 여기에서는 SUM()
--over() 안의 partition by는 group by 역할을 한다. 분석에 대한 범위를 지정하는 역할.

/*
ENAME            SAL ASC순으로_부서별_SAL누적 부서별_SAL합계 DEPTNO_SAL_ASC정렬후_누적    SAL총계
---------- --------- ------------------------ -------------- ------------------------- ----------
MILLER       1300.00                     1300           8750                      1300      29025
CLARK        2450.00                     3750           8750                      3750      29025
KING         5000.00                     8750           8750                      8750      29025
SMITH         800.00                      800          10875                      9550      29025
ADAMS        1100.00                     1900          10875                     10650      29025
JONES        2975.00                     4875          10875                     13625      29025
SCOTT        3000.00                    10875          10875                     19625      29025
FORD         3000.00                    10875          10875                     19625      29025
JAMES         950.00                      950           9400                     20575      29025
WARD         1250.00                     3450           9400                     23075      29025
MARTIN       1250.00                     3450           9400                     23075      29025
TURNER       1500.00                     4950           9400                     24575      29025
ALLEN        1600.00                     6550           9400                     26175      29025
BLAKE        2850.00                     9400           9400                     29025      29025

14 rows selected
*/


--사원 중 직무별로 가장 많은 월급을 받는 사람의 사원번호, 직무명, 월급을 출력하라
 
SELECT T1.EMPNO, T2.JOB, T2.MAX_SAL
FROM EMP T1,
          (SELECT JOB, MAX(SAL) AS MAX_SAL 
            FROM EMP
            GROUP BY JOB) T2
WHERE T1.JOB = T2.JOB
AND T1.SAL = T2.MAX_SAL;

/*

EMPNO JOB          MAX_SAL
----- --------- ----------
 7788 ANALYST         3000
 7902 ANALYST         3000
 7934 CLERK           1300
 7566 MANAGER         2975
 7839 PRESIDENT       5000
 7499 SALESMAN        1600

6 rows selected
*/

--아래와 같이 분석함수를 사용하면 위와 똑같은 결과를 가져올 수 있다. 
--놀라운 것은 테이블을 한번만 읽어서 처리를 할 수 있다는 것이다. 
select empno, job, max_job_sal sal
from (
select 
         empno
       , job
       , sal
       , max(sal) over (partition by job) max_job_sal 
from emp ) 
where sal = max_job_sal;

/*
EMPNO JOB              SAL
----- --------- ----------
 7788 ANALYST         3000
 7902 ANALYST         3000
 7934 CLERK           1300
 7566 MANAGER         2975
 7839 PRESIDENT       5000
 7499 SALESMAN        1600

6 rows selected
*/

--모든 사원의 월급의 평균에 가장 근접한 사원의 사번과 월급 출력
select empno, sal
from (
      select
              empno
            , min(abs_sal) over() min_sal
            , abs_sal
            , sal
      from (
            select
                    empno
                  , sal
                  , abs(sal - avg(sal) over()) abs_sal
            from emp) )
where abs_sal = min_sal;

/*
SQL> select avg(sal) from emp;

  AVG(SAL)
----------
2073.21428

EMPNO       SAL
----- ---------
 7782   2450.00
*/ 

--부서별로 일련번호를 붙이되 각각의 부서마다 1로 시작하는 일련번호를 붙인다.

SELECT
        deptno
      , empno
      , ename
      , row_number() over(PARTITION BY deptno ORDER BY deptno)
FROM emp;

/*
DEPTNO EMPNO ENAME      ROW_NUMBER()OVER(PARTITIONBYDE
------ ----- ---------- ------------------------------
    10  7782 CLARK                                   1
    10  7839 KING                                    2
    10  7934 MILLER                                  3
    20  7369 SMITH                                   1
    20  7876 ADAMS                                   2
    20  7902 FORD                                    3
    20  7788 SCOTT                                   4
    20  7566 JONES                                   5
    30  7499 ALLEN                                   1
    30  7698 BLAKE                                   2
    30  7654 MARTIN                                  3
    30  7900 JAMES                                   4
    30  7844 TURNER                                  5
    30  7521 WARD                                    6

14 rows selected
*/

--부서별 월급이 많은 순서대로 순위구하기
SELECT
        empno
      , ename
      , sal
      , rank() over(PARTITION BY deptno ORDER BY sal DESC)
FROM emp;

/*
--rank() over(PARTITION BY deptno ORDER BY sal DESC)를 
--rank() over(PARTITION BY deptno ORDER BY sal ASC)로 고치면 역순이 된다. 
--rank()는 동일 순위에 대하여 동일한 값을 리턴하지만 공백이 생긴다.
--즉, 1위에 해당된느 행이 2개이면 2는 존재하지 않고, 바로 3으로 넘어간다.

EMPNO ENAME            SAL RANK()OVER(PARTITIONBYDEPTNOOR
----- ---------- --------- ------------------------------
 7839 KING         5000.00                              1
 7782 CLARK        2450.00                              2
 7934 MILLER       1300.00                              3
 7788 SCOTT        3000.00                              1
 7902 FORD         3000.00                              1
 7566 JONES        2975.00                              3
 7876 ADAMS        1100.00                              4
 7369 SMITH         800.00                              5
 7698 BLAKE        2850.00                              1
 7499 ALLEN        1600.00                              2
 7844 TURNER       1500.00                              3
 7521 WARD         1250.00                              4
 7654 MARTIN       1250.00                              4
 7900 JAMES         950.00                              6
*/



SELECT
        empno
      , ename
      , sal
      , dense_rank() over(PARTITION BY deptno ORDER BY sal DESC)
FROM emp;

/*
dense_rank()는 rank()와는 달리 1위가 2개 존재하면 다음의 순위는 2가 된다.

EMPNO ENAME            SAL DENSE_RANK()OVER(PARTITIONBYDE
----- ---------- --------- ------------------------------
 7839 KING         5000.00                              1
 7782 CLARK        2450.00                              2
 7934 MILLER       1300.00                              3
 7788 SCOTT        3000.00                              1
 7902 FORD         3000.00                              1
 7566 JONES        2975.00                              2
 7876 ADAMS        1100.00                              3
 7369 SMITH         800.00                              4
 7698 BLAKE        2850.00                              1
 7499 ALLEN        1600.00                              2
 7844 TURNER       1500.00                              3
 7521 WARD         1250.00                              4
 7654 MARTIN       1250.00                              4
 7900 JAMES         950.00                              5
*/

--TOP n개 가져오기
SELECT 
         empno
       , ename
       , sal
       , rank
FROM (
      SELECT
              empno
            , ename
            , sal
            , rank() over(PARTITION BY deptno ORDER BY sal DESC) rank
      FROM emp)
WHERE rank <= 3;    

/*

경우에 따라서 rank(), dense_rank()를 사용한다. 

EMPNO ENAME            SAL       RANK
----- ---------- --------- ----------
 7839 KING         5000.00          1
 7782 CLARK        2450.00          2
 7934 MILLER       1300.00          3
 7788 SCOTT        3000.00          1
 7902 FORD         3000.00          1
 7566 JONES        2975.00          3
 7698 BLAKE        2850.00          1
 7499 ALLEN        1600.00          2
 7844 TURNER       1500.00          3

*/

--피봇
SELECT
         deptno
       , max(CASE WHEN rank = 1 THEN sal END) rank_1
       , max(CASE WHEN rank = 2 THEN sal END) rank_2
       , max(CASE WHEN rank = 3 THEN sal END) rank_3
FROM (
      SELECT 
               sal
             , deptno
             , rank
      FROM (
            SELECT
                    sal
                  , deptno
                  , rank() over(PARTITION BY deptno ORDER BY sal DESC) rank
            FROM emp)
      WHERE rank <= 3 )
GROUP BY deptno      

/*
DEPTNO     RANK_1     RANK_2     RANK_3
------ ---------- ---------- ----------
    10       5000       2450       1300
    20       3000                  2975
    30       2850       1600       1500
*/      

--앞 뒤행 가져오기 lead() lag()
--입사일에 차이에 따른 전/후 월급차이
SELECT 
         empno
       , ename
       , sal - lag(sal, 1) over(ORDER BY hiredate) pre
       , sal
       , sal - lead(sal, 1) over(ORDER BY hiredate) NEXT
FROM emp;

/*
EMPNO ENAME             PRE       SAL       NEXT
----- ---------- ---------- --------- ----------
 7369 SMITH                    800.00       -800
 7499 ALLEN             800   1600.00        350
 7521 WARD             -350   1250.00      -1725
 7566 JONES            1725   2975.00        125
 7698 BLAKE            -125   2850.00        400
 7782 CLARK            -400   2450.00        950
 7844 TURNER           -950   1500.00        250
 7654 MARTIN           -250   1250.00      -3750
 7839 KING             3750   5000.00       4050
 7900 JAMES           -4050    950.00      -2050
 7902 FORD             2050   3000.00       1700
 7934 MILLER          -1700   1300.00      -1700
 7788 SCOTT            1700   3000.00       1900
 7876 ADAMS           -1900   1100.00 
*/

--특정 범위내의 첫행/끝행 
SELECT DEPTNO,ENAME,SAL,
       FIRST_VALUE(ENAME) OVER(PARTITION BY DEPTNO 
                               ORDER BY SAL DESC
                               ROWS BETWEEN UNBOUNDED PRECEDING 
                                        AND UNBOUNDED FOLLOWING) AS FV,
       LAST_VALUE(ENAME) OVER(PARTITION BY DEPTNO
                              ORDER BY SAL DESC
                              ROWS BETWEEN UNBOUNDED PRECEDING 
                                       AND UNBOUNDED FOLLOWING) AS LV                                        
FROM EMP;

/*
DEPTNO ENAME            SAL FV         LV
------ ---------- --------- ---------- ----------
    10 KING         5000.00 KING       MILLER
    10 CLARK        2450.00 KING       MILLER
    10 MILLER       1300.00 KING       MILLER
    20 SCOTT        3000.00 SCOTT      SMITH
    20 FORD         3000.00 SCOTT      SMITH
    20 JONES        2975.00 SCOTT      SMITH
    20 ADAMS        1100.00 SCOTT      SMITH
    20 SMITH         800.00 SCOTT      SMITH
    30 BLAKE        2850.00 BLAKE      JAMES
    30 ALLEN        1600.00 BLAKE      JAMES
    30 TURNER       1500.00 BLAKE      JAMES
    30 WARD         1250.00 BLAKE      JAMES
    30 MARTIN       1250.00 BLAKE      JAMES
    30 JAMES         950.00 BLAKE      JAMES
*/


--RATIO_TO_REPORT : 그룹에서 현재 행의 비율
SELECT JOB, ENAME, SAL, 
       RATIO_TO_REPORT(SAL) OVER(PARTITION BY JOB) AS RR
FROM EMP
ORDER BY JOB, ENAME;

/*
JOB       ENAME            SAL         RR
--------- ---------- --------- ----------
ANALYST   FORD         3000.00        0.5
ANALYST   SCOTT        3000.00        0.5
CLERK     ADAMS        1100.00 0.26506024
CLERK     JAMES         950.00 0.22891566
CLERK     MILLER       1300.00 0.31325301
CLERK     SMITH         800.00 0.19277108
MANAGER   BLAKE        2850.00 0.34441087
MANAGER   CLARK        2450.00 0.29607250
MANAGER   JONES        2975.00 0.35951661
PRESIDENT KING         5000.00          1
SALESMAN  ALLEN        1600.00 0.28571428
SALESMAN  MARTIN       1250.00 0.22321428
SALESMAN  TURNER       1500.00 0.26785714
SALESMAN  WARD         1250.00 0.22321428
*/

--
SELECT ENAME,SAL,
       COUNT(*) OVER(ORDER BY SAL
                     RANGE BETWEEN 149 PRECEDING 
                               AND 0 FOLLOWING) AS m_cnt
FROM EMP;

/*
ENAME            SAL      M_CNT
---------- --------- ----------
SMITH         800.00          1
JAMES         950.00          2  ---> 950 - 150  ~  950 + 0, 만약 149로 범위를 줄이면 1로 된다. 
ADAMS        1100.00          2
WARD         1250.00          3
MARTIN       1250.00          3
MILLER       1300.00          3
TURNER       1500.00          1
ALLEN        1600.00          2
CLARK        2450.00          1
BLAKE        2850.00          1
JONES        2975.00          2
SCOTT        3000.00          4
FORD         3000.00          4
KING         5000.00          1
*/

4 추가자료 #


사용자스키마

Describe 사용자스키마 here
사용자 스키마에 대해서...

여기서 사용자 스키마라 하면...사용자가 소유한 오라클의 객체를 의미합니다..
즉, 테이블, 인덱스, 뷰, 클러스터, 시퀀스, 시노님, 데이타베이스 링크등을 말하고 있습니다..
이 단원에서는 테이블을 생성하는 방법등 여러 사용자 스키마에 대한 전반적이 내용을 다룰 것입니다..
지금까지 오라클 스토리지와 관련될 것입니다...

먼저 관계형 데이타베이스의 데이타에 대한 표현 방식인 테이블에 대해서 알아보겠습니다..
분할등의 약간 고급에 속하는 것들은 따로 다루겠습니다..

테이블을 만들때는 블록 파라미터와 익스텐트 파라미터 모두 명시할 수 있습니다...
이것을 명시하지 않으면 기본값을 사용하게 됩니다..
익스텐트는 테이블스페이스를 만들당시 default storage 옵션 절에서 명시한 것을 따르게 됩니다..
자세한 문법은 메뉴얼을 참고하시구여..

여기서 못보던 파라미터들이 몇개 눈에 들어옵니다..
CLUSTER, ENALBE/DISABLE, AS 라는 것입니다...
클러스터에 관한것은 클러스터가 나올때 야그하구여..
활성화/비활성화는 제약조건의 활성화/비활성화를 의미합니다...AS다음에 오는 쿼리문을 통해서..
새로운 테이블을 만들수 도 있습니다...

그럼...vi에디터를 통해서 테이블을 만들어 보겠습니다..

SQL> !vi $ORACLE_HOME/sample.sql

-- dept table create
create table yasi.dept(
        deptno          number(2)       constraint pk_dept primary key,
        deptname        varchar2(10)    not null
)
pctfree 20 pctused 50
tablespace users
storage (initial 128k next 128k pctincrease 5);

-- emp table create
create table yasi.emp(
        empno           number          constraint pk_emp primary key,
        ename           varchar2(20)    not null,
        job             varchar2(20),
        hiredate        date            default sysdate,
        deptno          number(2)       constraint nn_deptno not null
                                        constraint fk_deptno references yasi.dept(deptno)
)
pctfree 5 pctused 75
tablespace users
storage ( initial 128k next 128k pctincrease 5);
~
~
~
~
~
~
~
~
:wq

SQL> @$ORACLE_HOME/sample.sql

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


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

SQL>

중요한것은 이러한 문법들이 아닙니다...테이블을 생성한다는 것은 이미 그 전에 많은 작업이 있었음을 의미합니다..
현실을 직관적으로 바라보고 이를 최대한 반영하는 것이 테이블 설계자의 목표입니다..
무턱대고 테이블을 생성해서는 안됍니다...
이것은 그냥 예제로 보인것이구여...암튼...무엇을 데이타화 할 것인가를 고민해야합니다..
이런것들은 책을 보면 금방 할 수 있는 것들이니까여...

다음은 테이블 수정에 관해서 살펴보겠습니다...
테이블의 수정이라함은 새로운 컬럼을 추가, 제약 사항의 추가 또는 변경, 데이타가 없는 경우는 데이타 타입의 변환도 가능합니다..
스토리지 옵션도 변경할 수 있습니다...
이미 생성된 컬럼명은 변경할 수 없습니다...
추가적으로 옵션이 몇개가 더 붙습니다..
기본 문법은 메뉴얼을 참고하시구여....
추가적인 못보던 스토리지 옵션만 살펴보겠습니다..

ALTER TABLE table
	[ALLOCATE EXTENT     SIZE int[K or M] | DATAFILE 'filename']
	[DEALLOCATE UNUSED   [KEEP int[K or M]] ]

여기서 ALLOCATE EXTENT의 의미는 기존의 데이타 파일에 새로운 익스텐트를 추가한다는 뜻입니다..
DEALLOCATE UNUSED는 프리 스페이스를 재사용 가능하게 만들어 줍니다..여기에 KEEP 옵션을 더하면 명시한 만큼의
공간은 계속 유지하도록 지정하는 것입니다..

SQL> connect yasi/yasi
연결되었습니다.

SQL> alter table emp
  2    add (comm number(10),
  3         loancode char(1) not null)
  4  allocate extent ( size 2M datafile '$ORACLE_HOME/oradata/ORCL/users01.dbf');          <-------수동으로 해당 데이타파일에 익스텐트 추가

테이블이 변경되었습니다.

SQL> alter table emp                        <--------- 컬럼의 데이타형변경과 스토리지 옵션 변경
  2      modify (comm number(8),
  3             loancode char(1) null)
  4  pctfree 20 pctused 50;

테이블이 변경되었습니다.

SQL> alter table dept                                   <----------------- 제약조건의 활성화/비활성화
  2  disable constraint pk_dept cascade;

테이블이 변경되었습니다.

SQL> alter table dept
  2  enable primary key;

테이블이 변경되었습니다.

SQL> alter table emp
  2  enable primary key;

테이블이 변경되었습니다.

SQL> create table before_name (id number);

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

SQL> insert into before_name values (1);

1 개의 행이 만들어졌습니다.

SQL> rename before_name to after_rename;            <------------------- 테이블명 바꾸기..

테이블명이 바뀌었습니다.

SQL> select * from after_rename;

        ID
----------
         1

테이블의 삭제는 drop table table_name으로 수행합니다...아주 쉽습니다...
생각해줘야 할것은 테이블을 삭제해도 그에 딸린 식구덜 까지 모두 삭제가 되는 것은 아닙니다..
즉, 프로시저라든지 함수, 트리거 같은 것은 지워지지 않습니다..
그러므로 개발시에 문서화가 상당히 중요하겠지여...

테이블에서 데이타를 삭제할때는 delete나 truncate문을 사용합니다...
주의할 것은 delete는 롤백시킬수 있으나 truncate는 롤백이 되지 않고 자동커밋됩니다..

테이블에 대해서 너무나도 간단히 알아봤습니다...기초적인 부분은 생략했구여....단지 사용법만을 언급했습니다..
처음에만 구현이란 것이 어렵지...조금 하다보면 구현이 어려운 것은 아닙니다..
잘 설계된 것을 실제로 옮기는 작업도 물론 중요하지만..그 전에 많은 노력을 통해 정돈된 것을 옮기는 것이기 때문에..
당연히 구현할 때도 잘 정돈된 구현상태가 되겠죠...
흠....이 개발에 대해서는 나중에 따로 실제예를 들어서 설명하도록 하겠습니다...지금 건덕지를 찾고 있는데..
그리 마땅한게 없네여..쩝..

다음에 인덱스가 있는데...이것은 다른 단원에서 다루겠습니다..
인덱스는 데이타를 빠르게 가져오기 위한 메카니즘이죠...만약 인덱스가 없었더라면 오라클이 존재하지 않았을 수도 있습니다...
헐헐~ 그만큼 인덱스는 중요합니다...
일단 저런 메카니즘이란 것만 언급하구여...

클러스터를 살펴보겠습니다..
클러스터 역시 빠른 조회(조인에서)를 위한 저장 메카니즘이기도 합니다...
머...별다른 조치없이 자주 테이블들이 묶여서 조회가 된다면 이 테이블들을 하나의 그룹으로 묶는 것이죠..
이것은 단지 조회의 잇점을 살리기 위한 메카니즘입니다..
삽입이나 갱신 같은 작업에는 일반적인 테이블보다 성능이 많이 저하됩니다..
이런 부가적인 단점에도 불구하고 클러스터는 조회의 성능을 높이기 위해서 사용될 수 있습니다..
클러스터로 테이블이 묶으면.. 연관된 데이타 행들이 같은 데이타 블록에 저장됨으로 디스크 I/O를 줄여줍니다..
자칫 잘못 생각하면 클러스터를 하면 저장공간을 더 많이 차지할 꺼라 생각할 수도 있습니다.(저도 그랬어용..)
그러나 클러스터 키는 한번만 인덱스에 저장되기 때문에 중복데이타가 많은 인덱스의 경우 그 공간을 줄여주기도 합니다...
상식으로 생각해 보아도 두개의 테이블 양쪽에 똑같은 컬럼이 외부키로 존재할 수 있습니다..이것이 합쳐져서 한개로 쓴다면..
오히려 저장공간은 감소합니다...

클러스터는 클러스터된 테이블의 컬럼에 클러스터 키를 가지고  클러스터로 연관된 데이타를 구분합니다..
클러스터 키는 인덱스를 가지는데 이를 클러스터 인덱스라고 합니다.. 클러스터 키값은 데이타 블록을 직접 포인트하고 있기 때문에
최소 두번의 디스크 입/출력만으로 데이타를 조회할 수 있습니다..
클러스터 인덱스가 없는 데이타를 조회하지 못하고, 클러스터에 데이타를 저장하기 위해서는 반드시 클러스터 인덱스를 생성해야 합니다..

정리하자면 클러스터의 생성단계는 다음과 같습니다...

클러스터 생성 --> 클러스터 인덱스 생성 --> 클러스터 테이블 생성

클러스터 생성 문법은 create cluster로 하면 되는데..나머지 옵션들은 사용이 같습니다..
그러나..한가지 size는 다른 오라클 객체와 좀 다르게 사용됩니다..
즉, 클러스터에서의 size란 하나의 데이타 블록에 같이 저장될 수 있는 클러스터 키의 총수를 결정짓는 옵션입니다..
따라서 size의 결정은 클러스터 생성시 가장 신중해야 합니다...
적정선에서 너무 크게도 너무 작게도 설정해주면 안돼겠지여...
size가 너무 작게 설정되면 여러 블럭에 걸쳐서 저장되니까 디스크 i/o를 추가적으로 발생시킴으로 성능이 저하될 수 도 있구여..
너무 크게 잡았다면 저장공간을 낭비하는 꼴이 될 수 있습니다..

클러스터 인덱스의 문법도 역시 메뉴얼을 참고하시구여...
이제 직접 클러스터링을 해보겠습니다...(주의: 여기서 말하는 클러스터링과 OS에서 말하는 클러스터링을 헤깔리지 마세용~)

위에서 썻던 sample.sql을 사용해 봅시다...
먼저 생성했던 테이블을 삭제하고여...

SQL> drop table dept cascade constraints;

테이블이 삭제되었습니다.

SQL> drop table emp;

테이블이 삭제되었습니다.

SQL> create cluster cluster_dept_emp(               <------------- 클러스터 생성
  2     deptno number(2)
  3  )
  4  size 400
  5  tablespace users
  6  ;

클러스터가 생성되었습니다.

SQL> create index ind_cluster_dept_emp               <------------ 클러스터 인덱스 생성
  2  on cluster cluster_dept_emp
  3  tablespace indx;

인덱스가 생성되었습니다.

SQL> @$ORACLE_HOME/sample.sql                        <-------------- 테이블 생성

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


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


클러스터를 변경할 수 있는 사항들은 클러스터 생성시의 문법에 나온 옵션을 모두 수정할 수 있습니다..

클러스터를 삭제하면 클러스터에 포함된 모든 테이블과 클러스터인덱스가 함께 삭제됩니다..
또한 클러스터에 할당되었던 모든 익스텐트는 테이블스페이스로 복구되어 다른 세그먼트에 의해 사용 가능한
상태가 됩니다..
문법은 다음과 같습니다..

DROP CLUSTER cluster
   INCLUDING TBLES [CASCADE CONSTRAINTS]
   
클러스터 삭제시 INCLUDING TBLES 옵션을 주지 않는다면 클러스터를 삭제 할 수 없습니다..
먼저 해당 테이블을 삭제한 후에 클러스터를 삭제해 주어야 합니다..

클러스터에 대한 야그는 나중에 나오는 튜닝부분에서 좀더 다루도록 하겠습니다...

다음은 해싱을 살펴보겠습니다..
오라클에서 말하는 해싱은 테이블의 컬럼으로 해시함수를 제공하고, 그 해시 함수의 결과에 따라 데이타 행을 
저장하는 방법을 가리킵니다..
이러한 해싱은 '=' 조건에서 상당히 빠른 성능을 보장합니다..
다음은 해싱과 인덱스를 사용하는 경우를 나열한 것입니다..

해싱사용의 경우
	- 테이블의 크기에 변화가 엇는 경우..즉, 데이타의 삭제, 갱신, 입력이 잘 일어나지 않는 경우
	- 해시된 컬럼들에 대하여 항상 일정하게 같은 수의 조회가 이루어질때
	- 데이타 조회 작업의 성능 최적화가 가장 중요한 요소일때
	- 해키 키가 잘 분되어 있을때

인덱스를 사용하는 경우
	- 테이블의 크기가 고정적이지 않을 경우
	- 해시할 테이블의 크기를 예측할 수 없는 경우
	- 저장 공간을 미리 예측하여 할당할 수 없을때
	- 응용 프로그램이 테이블 전체 스캔작업을 자주 할때

해쉬에서 문제되는 것은 반환되는 값의 충돌문제입니다...
즉, 내가 원치 않게 해시함수에서 반환된 값이 다른 데이타를 가리킨다면 이것은 문제가 됩니다..
그러므로 해시값 중에서 데이타 행의 분산을 최대로 제공 할 수 있어야 합니다..

해시 클러스터의 생성 클러스터 생성 문법에...[HASHKEYS int [HASH IS expr] 이 더해진 문법입니다..
여기서의 SIZE는 가은 해시 키값으로서 저장되는 모든 데이타 행을 위한 공간의 크기를 지정하며, 그 기본값은
하나의 블록의 크기와 같습니다..

HASHKEYS 에서 지정한 값은 가장 가까운 소수로 변환합니다.. 이값을 100으로 설정한 경우 그 실제의 값은 101이 됩니다..
이 값의 최소값은 2입니다..
즉, 오라클의 해수는 소수를 이용한다는 뜻이 되겠죠...

해시클러스터의 크기는 다음과 같은 방법으로 추정할 수 있습니다..
예를 들면...

블록크기 = 2k
PCTFREE  = 10
SIZE     = 500
HASHKEYS = 40

이라면 

블록크기 - PCTFREE = 1800바이트
1800 / 500 = 3 나머지 300
즉, 하나의 블록당 3개의 해시키가 위치할 수 있는 것이고...나머지 300바이트에는 해시키가 위치할 수 없습니다..
다시말하면 하나의 블록당 3개의 해시키가 위치하고, 4번째 해시키는 다음 블록에 위치하게 되는 것입니다..
이런 식으로 41개의 해시키가 우치하기 위해서는 14개의 블록이 필요합니다...
마지막 블록에는 4개의 해쉬키만 존해하게 되구여..

이렇게 된다면 각 블록당 300 바이트의 저장공간의 손실을 보고 있습니다...
그러나 이것은 새로 들어올 행이나 갱신되는 행을 위해서 필요할 수도 있습니다..
만약 새로 저장되는 데이타 행이 위치할 데이타 블록의 크기보다 클 경우는 오버플로워 데이타 블록이 형성되어
추가적인 디스크 I/O를 유발하여 성능에 영향을 미치게 됩니다..
만약 해쉬키의 크기를 크게 설정하면 데이타를 저장하기 위한 더 많은 데이타블록이 요구되기 때문에 
저장공간의 낭비를 초래할 수 있습니다..

해쉬클러스터도 클러스터의 한 종류이기 때문에 먼저 클러스터를 생성한 후에
테이블을 생성합니다...
만약 해쉬에 대한 이해를 아직 못하신 분은 아까는 인덱스를 생성해 줬는데...왜 안해줄까 하시는 분덜도 계시리라 
생각합니다...이것은 아직 해쉬와 인덱스의 개념이 안잡히셔서 그러니..
다른 문서나 책을 참고하여 개념을 익히시기 바랍니다...
제가 간단히 말한다면 인덱스와 해쉬는 데이타에 빠르게 접근하기 위한 메카니즘입니다..
즉, 두개가 서로 다른 메카니즘이죠...그러니 인덱스를 써서 접근할 것인가..아니면 해쉬를 쓸것인가를 결정한 것이죠...
나무꾼이 나무를 하는데 도끼와 톱을 동시에 사용할 수는 없는 노릇이니까여..


SQL> create cluster sn_reserve (sn_number number(4))
  2  tablespace users
  3  size 500
  4  hashkeys 40
  5  hash is sn_number;

클러스터가 생성되었습니다.

SQL> create table bookID(
  2  sn nuber(4),
  3  bookname varchar2(10),
  4  salesprise number(9),
  5  retailprice number(9),
  6  stock number(6)
  7  )
  8  cluster sn_reserve(sn);
sn nuber(4),
        *
2행에 오류:
ORA-00907: 우괄호가 없습니다


SQL> c sn nuber(4)/sn number(4)
SP2-0023: 문자열이 없습니다.
SQL> c /sn nuber(4)/sn number(4)
  2* sn number(4),
SQL> run
  1  create table bookID(
  2  sn number(4),
  3  bookname varchar2(10),
  4  salesprise number(9),
  5  retailprice number(9),
  6  stock number(6)
  7  )
  8* cluster sn_reserve(sn)

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

SQL>

해쉬클러스터를 변경할 경우 size, hash is, hashkeys의 값은 변경할 수 없습니다..
그리고 해수 클러스터를 삭제할 경우 해당 테이블과 함께 삭제하려면 including tables 옵션을 설정하면 됩니다..

   
여기서 해쉬클러스터에 대한 야그를 마치고, 뷰에 대한 야그를 하겠습니다..
뷰는 기존의 테이블에서 파생된 또하나의 테이블이라고 보면 됩니다....그러나 실제로 존재하지 않는 테이블입니다..
즉, 가상 테이브입니다...select에 의해서 나온 결과물을 테이블화 한 것입니다..
즉, 창문을 통해서 밖을 내다보는 것과 같습니다...테이블을 사용하는 사용자를 우물한 개구리로 만들어 버리는 격이 될 수 있는 것입니다..

생성문법은 다음과 같습니다..

CREATE [OR REPLACE] [FORCE | NOFORCE] VIEW view_name
	AS subquery
	[WITH CHECK OPTION [ CONSTRAINT constraint]]
	[WITH READ ONLY]

OR REPLACE는 재생성의 의미를 가지고 있습니다..
FORCE는 실제로 존재하지 않는 테이블에 대해서 강제적으로 뷰를 생성할 때 쓰는 옵션입니다..
WITH CHECK OPTION 을 사용하면 서브쿼리에서 준 조건에 맞는 것만 적용한다는 뜻입니다...

뷰의 사용 목적은 상당히 다양합니다...
뷰를 잘 사용하면 고수라는 소리를 듣는다는 소리가 어쩌면 상당히 활용가치가 있기 때문이 아닌가 합니다..
사용목적을 살펴봅시당..

- 보안성
: 앞에서도 살펴보았습니다만...사용자를 우물안 개구리가 되게 하는 것입니다...
즉, 눈속임 또는 창을 통해서만 볼 수 있게 함으로써 보안성을 제공하는 것입니다...그러나 그렇게 보안에 좋은 방법은  아니라고 생각합니다...보통 뷰의 이름을 v_titles라든지 하는 원래 테이블의 이름을 암시적으로 알려주고 있어서리...암튼...보안성이 좋기는 하지여..

- 사용상의 편의
: 이것은 개발자가 여러개의 테이블을 조인할 경우 이를 단순화 시킵니다..
만약 3개의 테이블을 조인하려고 할때...약간은 복잡시렵습니다...이것을 먼저 두개의 테이블을 조인하는 뷰를 만들고...이 뷰와 다른 나머지 하나의 테이블을 조인시킨다면 상당히 단순화 되는 것입니다..

- 수행속도의 향상
: 특정 집합이 먼저 실행되도록 하거나...튜닝이 된 뷰를 생성한다면 수행속도의 향상을 기대할 수 있습니다..

- 융통성 향상
: 이부분은 어케보면 데이타베이스의 좋은 점이라고 볼수 있지여...
즉, 데이타의 독립성을 이야기하는 것입니다...사용자의 관점과 논리적인 부분...물리적인 부분이 독립적이여서..
데이타 모델이나...객체등이 변하더라도 사용자의 관점..즉, 어플리케이션에는 영향을 미치지 않도록 할 수 있다는 소리지여..

- SQL의 성능향상
:이것은 단순화와도 약간 연관화 되는 소리인데...복잡시련 규칙등을 단순화시키고, 실제로 존재하지 않는 컬럼으로 특정 뷰의 유도 속성으로 만들어서 오버헤드를 줄이고 처리과정을 단순화 시키는 것입니다..

- 임시작업등의 활용에 사용한다면 좋겠죠?

그럼 뷰를 생성하고..옵션을 사용해 봅시다..

SQL> connect scott/tiger
연결되었습니다.
SQL> select * from emp;

     EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM     DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
      7369 SMITH      CLERK           7902 80/12/17        800                    20
      7499 ALLEN      SALESMAN        7698 81/02/20       1600        300         30
      7521 WARD       SALESMAN        7698 81/02/22       1250        500         30
      7566 JONES      MANAGER         7839 81/04/02       2975                    20
      7654 MARTIN     SALESMAN        7698 81/09/28       1250       1400         30
      7698 BLAKE      MANAGER         7839 81/05/01       2850                    30
      7782 CLARK      MANAGER         7839 81/06/09       2450                    10
      7788 SCOTT      ANALYST         7566 87/04/19       3000                    20
      7839 KING       PRESIDENT            81/11/17       5000                    10
      7844 TURNER     SALESMAN        7698 81/09/08       1500          0         30
      7876 ADAMS      CLERK           7788 87/05/23       1100                    20
      7900 JAMES      CLERK           7698 81/12/03        950                    30
      7902 FORD       ANALYST         7566 81/12/03       3000                    20
      7934 MILLER     CLERK           7782 82/01/23       1300                    10

14 개의 행이 선택되었습니다.

SQL> create view v_emp
  2  as
  3  select empno, ename, job, hiredate
  4  from emp
  5  where deptno = 20;

뷰가 생성되었습니다.

SQL> select * from v_emp;

     EMPNO ENAME      JOB       HIREDATE
---------- ---------- --------- --------
      7369 SMITH      CLERK     80/12/17
      7566 JONES      MANAGER   81/04/02
      7788 SCOTT      ANALYST   87/04/19
      7876 ADAMS      CLERK     87/05/23
      7902 FORD       ANALYST   81/12/03

SQL> drop view v_emp;

뷰가 삭제되었습니다.

SQL> create view v_emp
  2  as
  3  select empno, ename, job, hiredate, deptno
  4  from emp
  5  where deptno = 20
  6  with check option;

뷰가 생성되었습니다.

SQL> select * from v_emp;

     EMPNO ENAME      JOB       HIREDATE     DEPTNO
---------- ---------- --------- -------- ----------
      7369 SMITH      CLERK     80/12/17         20
      7566 JONES      MANAGER   81/04/02         20
      7788 SCOTT      ANALYST   87/04/19         20
      7876 ADAMS      CLERK     87/05/23         20
      7902 FORD       ANALYST   81/12/03         20

6 개의 행이 선택되었습니다.

SQL> insert into v_emp values (7777, 'YASI', 'CLERK', sysdate, 20);

1 개의 행이 만들어졌습니다.

SQL> select * from v_emp;

     EMPNO ENAME      JOB       HIREDATE     DEPTNO
---------- ---------- --------- -------- ----------
      7369 SMITH      CLERK     80/12/17         20
      7566 JONES      MANAGER   81/04/02         20
      7788 SCOTT      ANALYST   87/04/19         20
      7876 ADAMS      CLERK     87/05/23         20
      7902 FORD       ANALYST   81/12/03         20
      7777 YASI       CLERK     01/12/10         20

6 개의 행이 선택되었습니다.

SQL> update v_emp
  2  set job = 'MANAGER'
  3  where empno = 7777;

1 행이 갱신되었습니다.

SQL> select * from v_emp;

     EMPNO ENAME      JOB       HIREDATE     DEPTNO
---------- ---------- --------- -------- ----------
      7369 SMITH      CLERK     80/12/17         20
      7566 JONES      MANAGER   81/04/02         20
      7788 SCOTT      ANALYST   87/04/19         20
      7876 ADAMS      CLERK     87/05/23         20
      7902 FORD       ANALYST   81/12/03         20
      7777 YASI       MANAGER   01/12/10         20

6 개의 행이 선택되었습니다.

SQL> select * from emp
  2  where empno = 7777;

     EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM     DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
      7777 YASI       MANAGER              01/12/10                               20

SQL> insert into v_emp values (8888, 'LEE', 'CLERK', sysdate, 30);
insert into v_emp values (8888, 'LEE', 'CLERK', sysdate, 30)
            *
1행에 오류:
ORA-01402: 뷰의 WITH CHECK OPTION의 조건에 위배 됩니다

SQL> create view v2_emp
  2  as
  3  select * from emp
  4  order by empno;          <---------- 오라클8.x버전에서는 order by 절을 사용할 수 없었으나, 8i 버전 이상에서는 가능해졌습니다..

뷰가 생성되었습니다.

SQL> alter view v2_emp compile;          <------- 보통 뷰의 변경은 뷰의 재컴파일시 사용된다..

뷰가 변경되었습니다.

	
다음은 뷰에 대한 데이타사전뷰입니다..

USER_VIEWS
ALL_VIEWS
DBA_VIEWS

뷰의 사용은 이정도로 마치고...나중에 SQL부분에서 뷰를 써먹는 경우를 살펴보겠습니다...(저는 개인적으로 뷰를 상당히 좋아합니당..)

다음으로 시퀀스를 살펴봅시다..
시퀀스를 생성하면 '주문번호가 생성되었습니다'라는 메세지가 나옵니다...
시퀀스는 일련번호를 생성하는 그런 것입니다..
문법은 메뉴얼 참고하시구여...여기서는 주의해야할 옵션 몇개만 살펴보겠습니다..
우선 MAXVLAUE/NOMAXVALUE가 잇는데...이 옵션은 시퀀스가 증가 될 수 있는 최대값을 나타냅니다..
MAXVALUE의 기본값은 1024입니다...NOMAXVALUE로 설정하면 무한대로 값이 올라가게 됩니다..
CYCLE이란 옵션이 있는데...이것은 시퀀스의 최대값에 도달하면 그 다음값으로 최초의 값이 되는 것입니다..
기본값은 순환하는 값이 아닙니다...
CACHE/NOCACHE라는 옵션이 있는데...이것은 캐시를 사용하도록 지정하는 것입니다...
이값을 지정하지 않으면 기본적으로 오라클은 20개의 값을 캐시합니다..

시퀀스 생성을 해보겠습니다..

SQL> create sequence seq_iii
  2  increament by 1
  3  start with 50
  4  maxvalue 100
  5  nocache
  6  nocycle;
increament by 1
*
2행에 오류:
ORA-00933: SQL 명령어가 올바르게 종료되지 않았습니다


SQL> c /increament by 1/increment by 1
  2* increment by 1
SQL> run
  1  create sequence seq_iii
  2  increment by 1
  3  start with 50
  4  maxvalue 100
  5  nocache
  6* nocycle

주문번호가 생성되었습니다.

SQL> select seq_iii.nextval from dual;

   NEXTVAL
----------
        50

SQL> select seq_iii.currval from dual;

   CURRVAL
----------
        50

SQL> create table seq_test (id number);

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

SQL> create table seq_test (id number);

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

SQL> insert into seq_test values (seq_iii.nextval);

1 개의 행이 만들어졌습니다.

SQL> select * from seq_test;

        ID
----------
        51

시퀀스의 변경은 모두 생성문법과 같은데 start with문이 없다는 것 뿐입니다...
즉, 이미 생성당시 시작할 시퀀스의 값이 정해졌기 때문입니다..
삭제는 drop sequence sequence_name 을 하시면 됩니다..

다음은 시노님에 대해서 살펴보겠습니다..
시노님은 오라클 객체에 대한 별칭을 제공하는 것입니다...
즉, 원격 데이타베이스나 아니면 다른 사용자의 객체를 참조할때의 투명성을 확보해 줍니다...
다음의 예를 보면 yasi사용자가 scott 사용자의 소유인 emp테이블을 조회할 때 scott.emp라고 표시합니다..

SQL> select * from scott.emp;

     EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM     DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
      7369 SMITH      CLERK           7902 80/12/17        800                    20
      7499 ALLEN      SALESMAN        7698 81/02/20       1600        300         30
      7521 WARD       SALESMAN        7698 81/02/22       1250        500         30
      7566 JONES      MANAGER         7839 81/04/02       2975                    20
      7654 MARTIN     SALESMAN        7698 81/09/28       1250       1400         30
      7698 BLAKE      MANAGER         7839 81/05/01       2850                    30
      7782 CLARK      MANAGER         7839 81/06/09       2450                    10
      7788 SCOTT      ANALYST         7566 87/04/19       3000                    20
      7839 KING       PRESIDENT            81/11/17       5000                    10
      7844 TURNER     SALESMAN        7698 81/09/08       1500          0         30
      7876 ADAMS      CLERK           7788 87/05/23       1100                    20
      7900 JAMES      CLERK           7698 81/12/03        950                    30
      7902 FORD       ANALYST         7566 81/12/03       3000                    20
      7934 MILLER     CLERK           7782 82/01/23       1300                    10
      7777 YASI       MANAGER              01/12/10                               20

15 개의 행이 선택되었습니다.

이렇듯 좀 불편하기도 하지여...항상 자신이 쓰려는 객체의 소유자를 알고 있어야 하니 말이죠...
이것을 시노님을 생성하면 간단히 소유자를 알지않고 있어도 어떤 객체를 쓸 것인지만 알면 됩니다..
동의어(시노님)을 생성해 봅시다..

SQL> create synonym emp for scott.emp;
create synonym emp for scott.emp
*
1행에 오류:
ORA-01471: 객체와 같은 이름의 동의어는 작성할 수 없습니다


SQL> create synonym employee for scott.emp;

동의어가 생성되었습니다.

SQL> select * from employee;

     EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM     DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
      7369 SMITH      CLERK           7902 80/12/17        800                    20
      7499 ALLEN      SALESMAN        7698 81/02/20       1600        300         30
      7521 WARD       SALESMAN        7698 81/02/22       1250        500         30
      7566 JONES      MANAGER         7839 81/04/02       2975                    20
      7654 MARTIN     SALESMAN        7698 81/09/28       1250       1400         30
      7698 BLAKE      MANAGER         7839 81/05/01       2850                    30
      7782 CLARK      MANAGER         7839 81/06/09       2450                    10
      7788 SCOTT      ANALYST         7566 87/04/19       3000                    20
      7839 KING       PRESIDENT            81/11/17       5000                    10
      7844 TURNER     SALESMAN        7698 81/09/08       1500          0         30
      7876 ADAMS      CLERK           7788 87/05/23       1100                    20
      7900 JAMES      CLERK           7698 81/12/03        950                    30
      7902 FORD       ANALYST         7566 81/12/03       3000                    20
      7934 MILLER     CLERK           7782 82/01/23       1300                    10
      7777 YASI       MANAGER              01/12/10                               20

15 개의 행이 선택되었습니다.

SQL> connect scott/tiger             <------------------------------------------------------ 소유자이므로 yasi사용자가 생성한 scott.emp 시노님이 적용된다..
연결되었습니다.
SQL> select * from employee;

     EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM     DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
      7369 SMITH      CLERK           7902 80/12/17        800                    20
      7499 ALLEN      SALESMAN        7698 81/02/20       1600        300         30
      7521 WARD       SALESMAN        7698 81/02/22       1250        500         30
      7566 JONES      MANAGER         7839 81/04/02       2975                    20
      7654 MARTIN     SALESMAN        7698 81/09/28       1250       1400         30
      7698 BLAKE      MANAGER         7839 81/05/01       2850                    30
      7782 CLARK      MANAGER         7839 81/06/09       2450                    10
      7788 SCOTT      ANALYST         7566 87/04/19       3000                    20
      7839 KING       PRESIDENT            81/11/17       5000                    10
      7844 TURNER     SALESMAN        7698 81/09/08       1500          0         30
      7876 ADAMS      CLERK           7788 87/05/23       1100                    20
      7900 JAMES      CLERK           7698 81/12/03        950                    30
      7902 FORD       ANALYST         7566 81/12/03       3000                    20
      7934 MILLER     CLERK           7782 82/01/23       1300                    10
      7777 YASI       MANAGER              01/12/10                               20

15 개의 행이 선택되었습니다.

SQL> connect system/manager
연결되었습니다.
SQL> select * from employee;
select * from employee
              *
1행에 오류:
ORA-00942: 테이블 또는 뷰가 존재하지 않습니다         <--------------- 즉, 위에서 생성한 시노님은 지역적이라는 것을 알수 있다..

SQL> connect yasi/yasi
연결되었습니다.
SQL> create public synonym employee for scott.emp;
create public synonym employee for scott.emp
*
1행에 오류:
ORA-01031: 권한이 불충분합니다                      <-------------- 공용(public) 시노님은 dba가 생성해야 한다..

SQL> connect system/manager
연결되었습니다.
SQL> create public synonym employee for scott.emp;

동의어가 생성되었습니다.

SQL> select * from employee;

     EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM     DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
      7369 SMITH      CLERK           7902 80/12/17        800                    20
      7499 ALLEN      SALESMAN        7698 81/02/20       1600        300         30
      7521 WARD       SALESMAN        7698 81/02/22       1250        500         30
      7566 JONES      MANAGER         7839 81/04/02       2975                    20
      7654 MARTIN     SALESMAN        7698 81/09/28       1250       1400         30
      7698 BLAKE      MANAGER         7839 81/05/01       2850                    30
      7782 CLARK      MANAGER         7839 81/06/09       2450                    10
      7788 SCOTT      ANALYST         7566 87/04/19       3000                    20
      7839 KING       PRESIDENT            81/11/17       5000                    10
      7844 TURNER     SALESMAN        7698 81/09/08       1500          0         30
      7876 ADAMS      CLERK           7788 87/05/23       1100                    20
      7900 JAMES      CLERK           7698 81/12/03        950                    30
      7902 FORD       ANALYST         7566 81/12/03       3000                    20
      7934 MILLER     CLERK           7782 82/01/23       1300                    10
      7777 YASI       MANAGER              01/12/10                               20

15 개의 행이 선택되었습니다.


이제 마지막으로 사용자 스키마에서 살펴볼 것은 데이타베이스 링크입니다..
데이타베이스 링크는 컴터가 두대 있어야지 실습이 가능합니다...물론 네트웍 환경도 셋팅이 
되어 있는 상태여야 하구여...
저는 컴터가 두대라서리 할수 있지만....이거 보시는 분덜은 어떨지 몰겠습니다..
흠...저는 첨에 이거 오라클 NET8설정하는데....무지 고생했습니다.....
하루죙일 이것만 쳐다보구 있었지여...
암튼....이렇게 서비스이름을 지정한 것을 @와 더불어 붙여줍니다..


SQL> connect scott/tiger
연결되었습니다.
SQL> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production                <---------- 유닉스 서버의 오라클 8.1.7 입니다..
PL/SQL Release 8.1.7.0.0 - Production
CORE    8.1.7.0.0       Production
TNS for Intel SVR4 UNIX: Version 8.1.7.0.0 - Development
NLSRTL Version 3.4.1.0.0 - Production

SQL> connect scott/tiger@ORCL
연결되었습니다.
SQL> select * from v$version;

BANNER
-----------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.0.1.1.1 - Production                <----------- 윈2000 서버의 오라클 9.0.1.1.1 입니다..           
PL/SQL Release 9.0.1.1.1 - Production
CORE    9.0.1.1.1       Production
TNS for 32-bit Windows: Version 9.0.1.1.0 - Production
NLSRTL Version 9.0.1.1.1 - Production

우리는 데이타베이스에 작업을 할때 이런식으로 작업을 하게 됩니다...
이것은 상당히 불편하지여...그래서 튀어나온 것이 데이타베이스 링크입니다..
사용자에게 상당한 투명성을 확보합니다...
즉, 데이타베이스 링크는 데이타베이스 서버로의 네트웍 연결을 위한 대체명이라고 할 수 있습니다..
다음은 데이타베이스 링크의 문법입니다...

CREATE [PUBLIC] DATABASE LINK link
CONNECT TO username IDENTIFIED BY passwd
Using service_name

직접 해봅시다..

SQL> create database link yasicom2001_Server
  2  connect to scott identified by tiger
  3  using 'ORCL';

데이타베이스 링크가 생성되었습니다.

SQL> select * from emp@yasicom2001_Server;

     EMPNO ENAME                JOB                       MGR HIREDATE        SAL       COMM     DEPTNO
---------- -------------------- ------------------ ---------- -------- ---------- ---------- ----------
      7369 SMITH                CLERK                    7902 80/12/17        800                    20
      7499 ALLEN                SALESMAN                 7698 81/02/20       1600        300         30
      7521 WARD                 SALESMAN                 7698 81/02/22       1250        500         30
      7566 JONES                MANAGER                  7839 81/04/02       2975                    20
      7654 MARTIN               SALESMAN                 7698 81/09/28       1250       1400         30
      7698 BLAKE                MANAGER                  7839 81/05/01       2850                    30
      7782 CLARK                MANAGER                  7839 81/06/09       2450                    10
      7788 SCOTT                ANALYST                  7566 87/04/19       3000                    20
      7839 KING                 PRESIDENT                     81/11/17       5000                    10
      7844 TURNER               SALESMAN                 7698 81/09/08       1500          0         30
      7876 ADAMS                CLERK                    7788 87/05/23       1100                    20
      7900 JAMES                CLERK                    7698 81/12/03        950                    30
      7902 FORD                 ANALYST                  7566 81/12/03       3000                    20
      7934 MILLER               CLERK                    7782 82/01/23       1300                    10

14 개의 행이 선택되었습니다.

SQL> drop database link yasicom2001_Server;       <--------- 삭제는 간단합니다..

데이타베이스 링크가 삭제되었습니다.


여기까지 사용자 스키마에 대해서 다루어 봤습니다.....
아직도 해야될 내용이 무궁무진 합니다....
머리가 지끈거리네여....지금이 새벽4시군여....헐헐~




오라클시작배치파일만들기

Describe 오라클시작배치파일만들기 here


@echo off
net start OracleServiceORCL
lsnrctl start
sqlplus /nolog @c:\oracle_start.sql

REM # 이 파일을 .bat파일로 저장하고, c:\oracle_start.sql 파일을 작성하세요.
REM # c:\oracle_start.sql 내용은 다음과 같습니다. 
REM # - 아 래 - 
REM # conn sys/password1! as sysdba
REM # startup force
REM # exit

테이블스페이스와데이타파일과온라인백업

Describe 테이블스페이스와데이타파일과온라인백업 here


==========================================
테이블스페이스와 데이타 파일과 온라인 백업
==========================================

오라클의 3구성 요소라구 하면...메모리, 프로세스, 파일로 볼 수 있습니다...
테이블스페이스는 논리적인 오라클의 구조를 말합니다...
이 논리적인 테이블스페이스와 연관되는 것이 바로 데이타 파일입니다..
테이블스페이스가 논리적으로 존재하면 해당 테이블스페이스에 속하는 데이타 파일도 존재해야 합니다..
이 관계가 깨진다면 데이타베이스 시스템의 오류이지여..
다시 말하면 테이블스페이스 하나당 여러개이 데이타 파일을 가질수 있으며,
또한 여러개의 세그먼트로 구성됩니다..

테이블스페이스는 최소 한개이상 존재해야 합니다...
그 기본적으로 존재하는 테이블스페이스가 system tablespace입니다..
시스템 테이블스페이스는 데이타베이스의 동작을 위해서 꼭 필요한 테이블스페이스입니다..
시스템 테이블스페이스에는 데이타 사전 정보와 프로시저, 패키지등의 정의가 정의되어 있습니다..
기본적으로 일반사용자가 생성되거나 일반사용자의 데이타가 이 시스템 테이블스페이스에
저장되지만 오라클 정도의 DBMS를 쓴다면...당연히 디스크 입/출력을 줄이기 위해서 
시스템 테이블스페이스는 분리되어야 합니다...(머 공부용으로는 상관이 없지만요..)
시스템 테이블스페이스는 시스템 테이블스페이스를 위한 롤백 세그먼트도 포함하고 있습니다..

시스템 테이블스페이스 이외에....테이블 스페이스는 다음과 같습니다..

SQL> select tablespace_name from dba_tablespaces;

TABLESPACE_NAME
------------------------------
SYSTEM
TOOLS
RBS
TEMP
USERS
INDX
DRSYS

7 개의 행이 선택되었습니다.

시스템 테이블스페이스를 제외하면 6개입니다..
이것은 기본적으로 오라클을 설치하면 이렇게 잡힙니다..
각각의 테이블스페이스를 분리하는 것은 디스크 I/O 경합을 줄이는데 이유가 있는 것입니다...

기본적인 테이블스페이스의 야그는 끝났구여...
이제 테이블스페이스를 만들어 봅시다..생성시 DBA 권한이 있는 사용자만 테이블스페이스를 생성할 수 있구여..
문법은 오라클 메뉴얼을 참고하시면 되겠습니다..저의 자료실에 있으니까 다운받으셔서 참고하시구여..
직접 실습을 해보도록 하겠슴다..
모든 옵션을 예에서 다 써보면서 각각을 보겠습니다..

SQL> create tablespace data1
  2  datafile '/export/home/oracle/8i/oradata/data1.dbf' size 5M
  3  default storage( initial 50k next 50k minextents 10 maxextents 121 pctincrease 0);

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


default storage 에 있는 값들은 익스텐트에 관한 기본 값입니다..
익스텐트를 할당할때 기본적으로 저런 형식에 맞추어 확장해 나간다는 의미입니다..

reuse라는 값을 사용해 봅시다..
앞에서 생성한 테이블스페이스를 지운다음 다시 사용하는 명령을 실행해 봅시다..

SQL> drop tablespace data1;
  
테이블 영역이 삭제되었습니다.

SQL> !ls /export/home/oracle/8i/oradata
ORCL       data1.dbf                           <---------------------- 운영체제상의 파일로는 그냥 남아있다..즉,논리적인 부분만 끊어버린 것이다..

SQL> create tablespace data1
  2  datafile '/export/home/oracle/8i/oradata/data1.dbf' reuse;

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

다음은 online/off라인 옵션을 써서 테이블스페이스를 생성당시 활성화/비활성화 시키는 옵션을
사용해서 테이블스페이스를 하나 생성해보겠습니다..
테이블스페이스 생성의 기본값은 online 입니다...여기서는 offline으로 비활성화 시켜보겠습니다..

SQL> create tablespace data2
  2  datafile '/export/home/oracle/8i/oradata/data2.dbf' size 5M
  3  default storage (initial 8k next 8k minextents 10 maxextents 121 pctincrease 0)
  4  offline;

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

SQL> select tablespace_name, status from dba_tablespaces;

TABLESPACE_NAME                STATUS
------------------------------ ---------
SYSTEM                         ONLINE
TOOLS                          ONLINE
RBS                            ONLINE
TEMP                           ONLINE
USERS                          ONLINE
INDX                           ONLINE
DRSYS                          ONLINE
DATA1                          ONLINE
DATA2                          OFFLINE               <------------- 지금 생성한 data2 테이블스페이스가 offline 인것을 확인

9 개의 행이 선택되었습니다.
 
PERMANENT/TEMPORARY 옵션을 사용해서 임시와 영구 테이블스페이스를 생성해보겠습니다..
기본값은 PERMANENT 인데...TEMPORARY 옵션을 사용해서 임시 테이블스페이스를 생성해보겠습니다..
즉, 임시테이블스페이스를 생성하면 임시객체를 저장할지를 설정해주는 옵션입니다..

SQL> create tablespace temp_data
  2  datafile '/export/home/oracle/8i/oradata/temp_data.dbf' size 5M
  3  temporary;

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

SQL> select tablespace_name, contents from dba_tablespaces;

TABLESPACE_NAME                CONTENTS
------------------------------ ---------
SYSTEM                         PERMANENT
TOOLS                          PERMANENT
RBS                            PERMANENT
TEMP                           TEMPORARY
USERS                          PERMANENT
INDX                           PERMANENT
DRSYS                          PERMANENT
DATA1                          PERMANENT
DATA2                          PERMANENT
TEMP_DATA                      TEMPORARY                <-------------- 임시 테이블스페이스가 생성된것 확인

10 개의 행이 선택되었습니다.

마지막으로 생성한 파일이 다 채워졌을 경우 자동으로 데이타 파일을 확장하는 옵션인 AUTOEXTEND를 
사용해서 테이블스페이스를 생성해보겠습니다..
형식은 다음과 같습니다..

AUTOEXTEND [OFF | ON] NEXT integer(K or M) MAXSIZE [UNLIMITED | integer(K or M)]

OFF를 해주면 이 기능을 비활성화 시킨다는 의미입니다...
중요한 것은 MAXSIZE 입니다.. 여기서 무한대로 잡아준다면...하드디스크를 몽땅 다쓴다는 의미인데...
만약 디스크가 모자랄 경우에는 에러를 발생시킵니다...
아래예는 기냥 실습을 위해서 만든 것입니다...
자동확장이란 것두...오라클에서 보면 추가적인 작업입니다...즉, 서버에 부하가 걸릴수 있다는 것입니다..
그러므로 테이블스페이스의 크기(데이타 파일의 크기)를 현실에 맞추어...또는 예상되는 데이타의 양에 
맞추어 설정을 해야 하겠습니다..

SQL> create tablespace autoextend_ts
  2  datafile '/export/home/oracle/8i/oradata/autoextend_data.dbf' size 500k
  3  autoextend on next 500k maxsize 10m;

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

SQL> create table test (id number)
  2  tablespace autoextend_ts;

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

SQL> select tablespace_name, bytes from dba_data_files;

TABLESPACE_NAME                     BYTES
------------------------------ ----------
TOOLS                            10485760
DRSYS                            20971520
USERS                            20971520
INDX                             20971520
RBS                             157286400
TEMP                             20971520
SYSTEM                          283115520
DATA1                             5242880
DATA2                             5242880
TEMP_DATA                         5242880
AUTOEXTEND_TS                      516096             <------------------확인..

11 개의 행이 선택되었습니다.

SQL> declare
  2     i number := 0;
  3  begin
  4  while i < 500000 loop
  5     insert into test values (i);
  6     i := i + 1;
  7  end loop;
  8  end;
  9  /                     <----------- 좀 기둘리세용~

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

SQL> select tablespace_name, bytes from dba_data_files;

TABLESPACE_NAME                     BYTES
------------------------------ ----------
TOOLS                            10485760
DRSYS                            20971520
USERS                            20971520
INDX                             20971520
RBS                             235929600
TEMP                             20971520
SYSTEM                          283115520
DATA1                             5242880
DATA2                             5242880
TEMP_DATA                         5242880
AUTOEXTEND_TS                     8257536           <------------ 자동확장 된것이 보인다..

11 개의 행이 선택되었습니다.

SQL> create tablespace local_manage_ts
  2  datafile '/export/home/oracle/8i/oradata/local_manage_data.dbf' size 5M
  3  extent management local uniform size 128k;

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


마지막에 보여준 예는 확장장역을 관리하는데...한블럭이 8k라고 가정한 것입니다..
즉, 하나의 확장영역은 총 16개의 블럭으로 구성된다는 것입니다...

테이블스페이스도 물론 수정할 수 있습니다...
관련문법에는 백업에 관련된 옵션도 있습니다..
이 백업에 관련된 것도 해보구여...
흠..관련 문법은 역시 메뉴얼을 참고하시구여...
역시 모든 옵션을 동원해서 테이블스페이스를 변경하는 예를 보겠습니다..

먼저 테이블스페이스의 제한된 저장공간이 모질랄 경우에 대해서 생각해 보겠습니다..
방법은 두가지입니다..
테이블스페이스에 데이타파일을 추가시키는 것이구...
또하나는 alter database 명령을 통해서 데이타파일의 크기를 재정의하는 것입니다..
data1 테이블스페이스에 크기를 늘려보겠습니다...

SQL> alter tablespace data1
  2  add datafile '/export/home/oracle/8i/oradata/data1_1.dbf' size 2M;

테이블 영역이 변경되었습니다.

SQL> select a.tablespace_name, b.name
  2  from dba_data_files a, v$datafile b
  3  where a.file_id = b.file#
  4  and a.tablespace_name = 'DATA1';

TABLESPACE_NAME                NAME
------------------------------ ----------------------------------------------
DATA1                          /export/home/oracle/8i/oradata/data1.dbf
DATA1                          /export/home/oracle/8i/oradata/data1_1.dbf

SQL> select tablespace_name, status from dba_tablespaces;

TABLESPACE_NAME                STATUS
------------------------------ ---------
SYSTEM                         ONLINE
TOOLS                          ONLINE
RBS                            ONLINE
TEMP                           ONLINE
USERS                          ONLINE
INDX                           ONLINE
DRSYS                          ONLINE
DATA1                          ONLINE
DATA2                          OFFLINE       <------------- ONLINE 으로 변경해보자..
TEMP_DATA                      ONLINE
AUTOEXTEND_TS                  ONLINE
LOCAL_MANAGE_TS                ONLINE

12 개의 행이 선택되었습니다.

SQL> alter tablespace data2
  2  online;

테이블 영역이 변경되었습니다.

SQL> select tablespace_name, status from dba_tablespaces
  2  where tablespace_name = 'DATA2';

TABLESPACE_NAME                STATUS
------------------------------ ---------
DATA2                          ONLINE


다음은 백업에 관련된 옵션을 살펴보겠습니다...
옵션에 [begin | end] backup 이란 것이 보입니다..
이것은 온라인(데이타베이스가 open상태) 일때 백업을 하는 것을 의미합니다..
여기서는 DATA1 테이블스페이스를 백업해보겠습니다..

SQL> alter tablespace data1
  2  begin backup;
alter tablespace data1
*
1행에 오류:
ORA-01123: 온라인 백업을 시작할 수 없습니다 매체 복구가 사용 불가로 되어 있습니다

헐헐~ 에러가 나는 군여...
왜그럴까요???
아직 하지는 않았지만...온라인 백업은 아카이브로그 모드에서만 작동을 하게됩니다..
데이타베이스가 운영중이기 때문에....백업하는 동안 무슨 변화가 일어난다면 안돼기 때문입니다..
아카이브 로그 모드는 온라인 리두로그 파일을 오프라인 스토리지에 한번더 백업하는 것을 의미합니다...
아카이브 로그 모드로 운영중이라면 상당히 안정적으로 데이타베이스를 운영할 수 있지만...
추가적인 저장장치와 또한 추가적인 서버의 작업이기 때문에....성능에 영향을 줄 수 있습니다..

그러면 아카이브 로그 모드로 변환을 해보겠습니다...

먼저 데이타베이스를 내린다음 파라미터 파일을 수정한후 다시 startup시켜줘야 합니다..
추가할 파라미터는 다음과 같습니다..

log_archive_start = true
log_archive_dest = '/export/home/oracle/8i/oradata/archive
log_archive_format = %.arc

SQL> !vi $ORACLE_HOME/dbs/initORCL.ora
                .
                .
                .
                .
                .
# INSTRUCTIONS: Edit this file and the other INIT files it calls for
# your site, either by using the values provided here or by providing
# your own.  Then place an IFILE= line into each instance-specific
# INIT file that points at this file.
#
# NOTE: Parameter values suggested in this file are based on conservative
# estimates for computer memory availability. You should adjust values upward
# for modern machines.
#
###############################################################################

AUDIT_TRAIL =DB
log_archive_start = true
log_archive_dest = /export/home/oracle/8i/oradata/archive
log_archive_format = %.arc

db_name = "ORCL"

db_domain = yasicom
                .
                .
                .
                .
                .
                .
SQL> connect sys/chage_on_install as sysdba
연결되었습니다.
SQL> shutdown
데이터베이스가 닫혔습니다.
데이터베이스가 마운트 해제되었습니다.
ORACLE 인스턴스가 종료되었습니다.
SQL> startup mount                          <------------ 데이타베이스에 변경을 가하려면 mount까지만 해야 한다..
ORACLE 인스턴스가 시작되었습니다.

Total System Global Area   87818400 bytes
Fixed Size                    73888 bytes
Variable Size              70795264 bytes
Database Buffers           16777216 bytes
Redo Buffers                 172032 bytes
데이터베이스가 마운트되었습니다.
SQL> alter database archivelog;              <--------------- 아카이브 로그 모드로 바꾼다..

데이타베이스가 변경되었습니다.

SQL> alter database open;

데이타베이스가 변경되었습니다.

SQL> archive log list;
데이터베이스 로그 모드              아카이브 모드
자동 아카이브             사용
아카이브 대상            /export/home/oracle/8i/oradata/archive
가장 오래된 온라인 로그 순서     4108
아카이브할 다음 로그   4109
현재 로그 순서           4110
SQL> 

이제 온라인 백업을 해보겠습니다...
아카이브 로그 모드로 변환한뒤....온라인 백업을 합니다..
온라인 백업은 간단합니다...
테이블스페이스를 백업모드로 변환한뒤..관련 데이타 파일을 다른 곳을 복사한후..
백업모드를 풀어주면 끝납니다...
하나의 테이블스페이스를 백업하므로 오라클에서는 부분백업이라고 하거나...
데이타베이스가 오픈 상태에서 백업하으로...오픈백업 또는 온라인 백업이라고 합니다...
직접 해보겠습니다..

SQL> alter tablespace data1 begin backup;             <------ 테이블스페이스를 백업모드로 전환

테이블 영역이 변경되었습니다.

SQL> !cp /export/home/oracle/8i/oradata/data1.dbf /export/home/oracle/8i/data01_20011209.dbf             <--- 운영체제상으로 복사

SQL> !cp /export/home/oracle/8i/oradata/data1_1.dbf /export/home/oracle/8i/data02_20011209.dbf

SQL> !ls /export/home/oracle/8i
Apache               data01_20011209.dbf  jis                  odg                  precomp              svrmgr
JRE                  data02_20011209.dbf  jlib                 oem_webstage         rdbms                sysman
admin                dbs                  jsp                  oracore              relnotes             wwg
assistants           doc                  ldap                 oradata              root.sh              xdk
bin                  install              lib                  ord                  slax
classes              jar                  md                   otrace               sqlj
converters           javavm               network              owm                  sqlplus
ctx                  jdbc                 ocommon              plsql                starterdb

SQL> alter tablespace data1 end backup;            <------- 백업모드를 풀어준다..

테이블 영역이 변경되었습니다.

SQL> connect system/manager
연결되었습니다.
SQL> alter tablespace data2 offline;

테이블 영역이 변경되었습니다.

SQL> alter tablespace data2
  2  rename datafile '/export/home/oracle/8i/oradata/data2.dbf' to '/export/home/oracle/8i/oradata/data2_a.dbf';
alter tablespace data2
*
1행에 오류:
ORA-01525: 데이터 파일을 이름 변경시 오류가 생겼습니다
ORA-01141: 데이터 9 파일 이름 바꾸기를 하는데 오류 - 새로운 '/export/home/oracle/8i/oradata/data2_a.dbf' 파일이 없습니다
ORA-01110: 9 데이터 파일: '/export/home/oracle/8i/oradata/data2.dbf'
ORA-27037: 파일 상태를 얻을 수 없습니다
Intel SVR4 UNIX Error: 2: No such file or directory
Additional information: 3


SQL> !mv /export/home/oracle/8i/oradata/data2.dbf /export/home/oracle/8i/oradata/data2_a.dbf

SQL> alter tablespace data2
  2  rename datafile '/export/home/oracle/8i/oradata/data2.dbf' to '/export/home/oracle/8i/oradata/data2_a.dbf';

테이블 영역이 변경되었습니다.

SQL> alter tablespace data2 online;

테이블 영역이 변경되었습니다.

SQL> select a.tablespace_name, b.name
  2  from dba_data_files a, v$datafile b
  3  where a.file_id = b.file# and a.tablespace_name = 'DATA2';

TABLESPACE_NAME                NAME
------------------------------ --------------------------------------------
DATA2                          /export/home/oracle/8i/oradata/data2_a.dbf       <------ 이름이 바뀌었다..


이제 테이블스페이스를 삭제해보자...
아까 만든..autoextend_ts 테이블스페이스를 삭제해보자..

SQL> drop tablespace autoextend_ts;
drop tablespace autoextend_ts
*
1행에 오류:
ORA-01549: 테이블스페이스가 비어있지 않으므로 INCLUDING CONTENTS 옵션을 사용해 주십시오        <------ test테이블이 들어 있어서 지워지지 않는다..


SQL> drop tablespace autoextend_ts
  2  including contents;                     <-------------- 이 옵션을 사용해야 테이블스페이스에 존재하는 모든 객체와 함께 삭제될 수 있다..

테이블 영역이 삭제되었습니다.

SQL> !ls $ORACLE_HOME/oradata
ORCL                   autoextend_data.dbf    data1_1.dbf            local_manage_data.dbf
archive                data1.dbf              data2_a.dbf            temp_data.dbf

SQL> !rm $ORACLE_HOME/oradata/autoextend_data.dbf      <--------------------------------------- 논리적인 부분만 끊어진 상태이므로 OS상에서 해당 파일을 지워줘야 한다..

SQL> !ls $ORACLE_HOME/oradata
ORCL                   data1.dbf              data2_a.dbf            temp_data.dbf
archive                data1_1.dbf            local_manage_data.dbf


이제 데이타베이스 수준에 데이타 파일을 다뤄봅시다...
일반적으로 운영체제는 동시에 열수 있는 파일이 얼마 되질 않습니다. 
그러므로 몇 개의 큰 데이터 파일을 유지하는 것이 작은 파일을 많이 갖는 것보다는 유리하다고 볼수 있습니다.
일반적으로 생각해도 파일은 각각의 크기를 가지고 있습니다.
물론 오라클의 파일들도 각각의 크기를 가지고 있습니다. 이는 테이블스페이스과 관련이 있습니다.
예를 들면, SYSTEM 테이블스페이스는 최소 하나의 데이터 파일을 가지고 있습니다.
파일의 구성은 SYSTEM 테이블스페이스가 가지고 있는 데이터 파일의 격리입니다.
즉, 다른 데이터파일등과 다른 디스크에 저장하는 하는 것입니다.
이것은 사용자가 자주 접근하는 SYSTEM 테이블스페이스가 포함하는 데이터 파일에 대한 
디스크의 경합을 줄이는데 목적이 있습니다. 즉, 성능이 향상된다는 것이죠..
성능부분에 대해서는 나중에 더 다루어 보도록 하고, 여기서는 좀더 일반적인 것을 알아보도록 하겠습니다.

오라클 인스턴스의 상한값은 DB_FILES의 매개변수로 제어된다. 이 값은 인스턴스를 사용하는 동안에만 적용됩니다.
자..매개변수 파일을 열어보자..
앞쪽에서 DB_FIELS 매개변수를 쉽게 찾을 수 있을 것입니다.
 
DB_FILES와 MAXDATAFILES의 사용은 옵션입니다. 이 값을 정해주지 않으면 기본적인 데이터 파일수는 운영체제에 따릅니다.
아마도 파라미터 파일에 최대값이 나타나 있을 것입니다..주석으로 표시되어서…
웬만하면 권장값을 사용하는 것이 좋습니다..

SQL> alter tablespace users
  2  add datafile 'E:\ORACLE\ORADATA\ORCL\USERS03.DBF' size 5M
  3  autoextend on
  4  next 64k
  5  maxsize 5M;

테이블 영역이 변경되었습니다.

SQL> alter database datafile 'E:\ORACLE\ORADATA\ORCL\USERS03.DBF'
  2  autoextend off;

데이타베이스가 변경되었습니다.


주의할 것은 alter tablespace 문장이 아니라 alter database라는 것입니다.
즉, 비활성화는 데이터베이스 차원에서 변경시켜야 된다는 소리죠...

이보다 더 명시적인 직접적이 사용자의 개입을 알아봅시당..
바로 위에서 생성한 데이터 파일의 크기를 줄여보구여..

SQL> alter database datafile 'E:\ORACLE\ORADATA\ORCL\USERS03.DBF'
  2  resize 4M;

데이타베이스가 변경되었습니다.

방금 크기를 줄였었는데..이는 아무때나 되는 것이 아닙니다…
벌써 4M가 넘는 데이터들이 데이터 파일을 차지하고 있으면 데이터 파일을 줄어들지 않고 에러를 리턴할 것입니다.
이런 식으로 다시 위 데이터 파일을 원상태로 해봅시다..

SQL> alter database datafile 'E:\ORACLE\ORADATA\ORCL\USERS03.DBF'
  2  resize 5M;

데이타베이스가 변경되었습니다.

SQL> alter database datafile 'E:\ORACLE\ORADATA\ORCL\USERS03.DBF'
  2  autoextend on;

데이타베이스가 변경되었습니다.

아주 쉽습니다…

다음은 데이터 파일의 가용성에 관한 것을 알보도록 하겠습티다..
가용성에 대한 것은 ARCHIVELOG MODE에서 데이터 파일의 온라인 설정과 
NOARCHIVELOG MODE에서 데이터 파일을 오프라인으로 설정하는 것입니다
주의해야 하는 것은 SYSTEM 테이블스페이스에 있는 파일 외에는 테이블스페이스를 
오프라인으로 설정해서 일시적으로 테이블스페이스의 모든 데이터 파일을 사용하지 못하도록 할 수 있다는 것입니다.. 
테이블스페이스를 다시 온라인으로 설정하려면 테이블스페이스에 이 파일들을 남겨 두어야 합니다.

NOARCHIVELOG MODE에서는 데이터 파일을 오프라인으로 설정하고 바로 DROP할 수 있다.

SQL> alter database datafile 'E:\ORACLE\ORADATA\ORCL\USERS03.DBF' OFFLINE DROP;

 
다음은 데이터 파일 이름 변경 및 위치를 재지정하는 것입니다... 이것은 위에서 해봤기 때문에 설명하고 넘어갑니다..
주의할 것은 SYSTEM 테이블스페이스에 있는 데이터 파일이름을 변경하거나 위치를 재지정하려면
데이터베이스가 마운트되었거나 닫힌 상태이여 합니다. 
이유는 SYSTEM 테이블스페이스를 오프라인으로 설정할 수 없기 때문입니다.
방법은 단일 테이블스페이스에 속한 데이터파일의 이름을 재지정하거나 위치를 재지정하는 것과 비스무리합니다.

데이터 파일의 데이터 블록의 검증은 파라미터 파일의 DB_BLOCK_CHECKSUM을 TRUE로 설정합니다.
DBWR 프로세스가 각 블록의 체크섬을 계산하여 블록의 헤더에 저장합니다.
체크섬을 사용하여 다음에 데이터 블록을 읽을 때 블록 훼손을 발견할 수 있습니다. 
훼손된 블록이 발생하면 ORA-01578 에러를 리턴합니다.
한가지 생각해야 될 점은 DB_BLOCK_CHECKSUM을 TRUE로 설정함으로서 기존에 안하던 짓을 하게끔 하므로 오버헤드가 발생한다는 것입니다.

다음은 데이터파일에 관련된 데이터 딕셔너리에 있는 것들이다.

USER_EXTENTS

DBA_EXTENTS

USER_SEGMENTS

DBA_SEGMENTS

USER_FREE_SPACE

DBA_FREE_SPACE

DBA_USERS

DBA_TS_QUOTAS

USER_TABLESPACES

DBA_TABLESPACES

DBA_DATA_FILES

V$DATAFILE













                                






SQL*Plus에서 실행계획보기

Contents

1 환경만들기
2 PLAN_TABLE,에 기록하기
3 테이블 통계 분석



1 환경만들기 #

1. 먼저..두개의 파일을 읽어 실행시킨다.
$ORACLE_HOME/admin/rdbms/utlxplan.sql



2. DBA권한을 가진 사용자로 로그인
$ORACLE_HOME/sqlplus/admin/plustrce.sql 실행

-> V$들에 대한 select권한을 허가
-> DBA에게는 plustrace 역할 허가

grant plustrace to scott;
set autotrace on

2 PLAN_TABLE,에 기록하기 #

  1. EXPLAIN PLAN SET STATEMENT_ID = 'TEST' FOR
  2. SELECT * FROM EMP;
  3.  
  4. SELECT LPAD(OPERATION, LENGTH(OPERATION) + 2 * (LEVEL -1)) ||
  5.        DECODE(ID, 0, 'Cost Estimate:' || DECODE(POSITION, '0', 'N/A', POSITION), NULL) || ''|| OPTIONS || 
  6.        DECODE(OBJECT_NAME, NULL, NULL, ':') || RPAD(OBJECT_OWNER, LENGTH(OBJECT_NAME) + 1, ',') || OBJECT_NAME ||
  7.        DECODE(OBJECT_TYPE, 'UNIQUE', ' (U) ', 'NIN_UNIQUE', '(NU)', NULL) ||
  8.        DECODE(OBJECT_INSTANCE, NULL, NULL, '('|| OBJECT_INSTANCE || ')') PLAN
  9. FROM PLAN_TABLE
  10. START WITH ID = 0 AND STATEMENT_ID = 'TEST'
  11. CONNECT BY PRIOR ID = PARENT_ID AND STATEMENT_ID = 'TEST';  
  12.  
* IE���� �ҽ� ����� �ٹٲ� �ȵ�. MS-Word � �ٿ� ��������. �ٹٲ� �Ǵ� ������: Chrome, Opera, Safari


3 테이블 통계 분석 #

  1. BEGIN
  2. DBMS_STATS.gather_table_stats(ownname=> 'SCOTT', tabname=> 'EMP', partname=> NULL);
  3. END; 
  4.  
* IE���� �ҽ� ����� �ٹٲ� �ȵ�. MS-Word � �ٿ� ��������. �ٹٲ� �Ǵ� ������: Chrome, Opera, Safari

INSERT/UPDATE/DELETE

Contents

1 INSERT
2 SEQUENCE
3 UPDATE
4 DELETE



1 INSERT #

  1.  
  2. INSERT문은 데이타를 삽입할때 사용합니다. 기본적인 문법은 다음과 같습니다.
  3.  
  4. INSERT INTO 테이블명(컬럼1, 컬럼2, ...)
  5. VALUES (DATA1, DATA2, ...);
  6.  
  7. 데이타를 입력하려면 먼저 선행되어야 하는 것일 무엇일까요? 당연히 테이블을 만들어야 합니
  8. 다. 테이블을 만드는 것은 그리 간단한 일이 아닙니다. 현실에 존재하는 제약사항을 표현하고,
  9. 물리적인 것까지 고려해서 테이블을 생성해야 합니다.
  10.  
  11. 일단 이 단원은 INSERT에 대한 개념을 이야기 하고자 하는 것이기 때문에 간략화한 문법만
  12. 소개하도록 하고, 그때 그때 필요한 것은 주석을 통해서 어떤 뜻인지만 알고 계시면 되겠습
  13. 니다. 자세한 것은 TABLE을 다루는 부분을 참고하시기 바랍니다.
  14.  
  15. 초간단 TABLE 생성 문법
  16.  
  17. CREATE TABLE 테이블명 (
  18. 컬럼명1 데이타형,
  19. 컬럼명2 데이타형, ....);
  20.  
  21.  
  22.  
  23. 단순한 테이블한개를 생성하고, 하나의 행을 삽입해보도록 하겠습니다. 우선은 INSERT를 하기
  24. 위한 사용자를 하나 생성해 보도록 하겠습니다. 무슨 소리인지 모르시는 분들은 무조건 따라
  25. 하시거나 다른 책이나 웹문서를 참고하시기 바랍니다.
  26.  
  27.  
  28.  
  29. SQL> CONNECT SYSTEM/MANAGER
  30. 연결되었습니다.
  31. SQL> CREATE USER INSERTER IDENTIFIED BY INSERTER
  32. 2 DEFAULT TABLESPACE USERS;
  33.  
  34. 사용자가 생성되었습니다.
  35.  
  36. SQL> GRANT CONNECT, RESOURCE TO INSERTER;
  37.  
  38. 권한이 부여되었습니다.
  39.  
  40. SQL> CREATE TABLE TEST_INSERT (
  41. 2 ID NUMBER PRIMARY KEY,
  42. 3 NAME VARCHAR(10));
  43.  
  44. 테이블이 생성되었습니다.
  45.  
  46. SQL> INSERT INTO TEST_INSERT VALUES(23, 'YASI');
  47.  
  48. 1 개의 행이 만들어졌습니다.
  49.  
  50. SQL> SELECT * FROM TEST_INSERT;
  51.  
  52. ID NAME
  53. ---------- ----------
  54. 23 YASI
  55.  
  56. SQL> -- 만약 컬럼의 순서를 바꾸어 입력하고 싶다면?? 컬럼의 순서를 바꿔 주면 된다.
  57. SQL> INSERT INTO TEST_INSERT(NAME, ID) VALUES ('이재학', 24);
  58.  
  59. 1 개의 행이 만들어졌습니다.
  60.  
  61.  
  62.  
  63. 여러분은 어떤 홈페이지에서 회원가입을 할 때 꼭 입력해야 하는 사항과 입력하지 않아도 되
  64. 는 사항들이 있는 것을 보았을 것입니다. 여기서 꼭 입력해야 한다는 것은 NOT NULL을 의미하
  65. 고 입력하지 않아도 되는 것은 NULL 값을 허용한다는 것입니다. 이러한 것은 어떤 식으로 입
  66. 력을 하는지 실습을 통해서 알아보도록 하겠습니다. 먼저 아래와 같은 테이블을 생성합니다.
  67.  
  68.  
  69.  
  70. SQL> CREATE TABLE STUDENT(
  71. 2 S_NUM CHAR(7) PRIMARY KEY,
  72. 3 S_NAME VARCHAR(8) NOT NULL,
  73. 4 S_PHONE VARCHAR(11));
  74.  
  75. 테이블이 생성되었습니다.
  76.  
  77.  
  78.  
  79. 컬럼의 수 보다 적은 데이타의 삽입
  80.  
  81. SQL> INSERT INTO STUDENT(S_NUM, S_NAME) VALUES('9555023', '이재학');
  82.  
  83. 1 개의 행이 만들어졌습니다.
  84.  
  85. SQL> INSERT INTO STUDENT(S_NUM, S_NAME, S_PHONE)
  86. 2 VALUES('9555007', '나병우', '01198101134');
  87.  
  88. 1 개의 행이 만들어졌습니다.
  89.  
  90. SQL> SELECT * FROM STUDENT;
  91.  
  92. S_NUM S_NAME S_PHONE
  93. ------- -------- -----------
  94. 9555023 이재학
  95. 9555007 나병우 01198101134
  96.  
* IE���� �ҽ� ����� �ٹٲ� �ȵ�. MS-Word � �ٿ� ��������. �ٹٲ� �Ǵ� ������: Chrome, Opera, Safari


2 SEQUENCE #

  1. 여러분이 테이블을 만들고 일련번호 자동으로 삽입하고자 할 때가 있을 것입니다. 이럴 때는
  2. 오라클의 시퀀스라는 객체를 생성해 줘야합니다. 시퀀스는 자동으로 증가하는 숫자를 생성해
  3. 주는 객체입니다. 문법은 다음과 같습니다.
  4.  
  5.  
  6.  
  7. CREATE SEQUENCE SEQUENCE_NAME
  8. INCREMENT BY 값
  9. START WITH 값
  10. MAXVALUE 값 / NOMAXVALUE
  11. MINVALUE 값 / NOMINVALUE
  12. CYCLE / NOCYCLE
  13. CACHE 값 / NOCACHE
  14. ORDER / NOODER;
  15.  
  16.  
  17.  
  18. 주의해야할 옵션 몇개를 살펴보면 우선 MAXVLAUE/NOMAXVALUE가 잇는데 이 옵션은 시퀀스가 증
  19. 가 될 수 있는 최대값을 나타냅니다. MAXVALUE의 기본값은 1024입니다. NOMAXVALUE로 설정하
  20. 면 무한대로 값이 올라가게 됩니다. CYCLE이란 옵션은 시퀀스의 최대값에 도달하면 그 다음값
  21. 으로 최초의 값이 되는 것입니다. 기본값은 순환하는 값이 아닙니다. CACHE/NOCACHE라는 옵션
  22. 은 캐시를 사용하도록 지정하는 것입니다. 이값을 지정하지 않으면 기본적으로 오라클은 20개
  23. 의 값을 캐시합니다.
  24.  
  25. 시퀀스 생성을 해보겠습니다..
  26.  
  27.  
  28.  
  29. SQL> CREATE sequence seq_iii
  30. 2 increament BY 1
  31. 3 start WITH 50
  32. 4 maxvalue 100
  33. 5 nocache
  34. 6 nocycle;
  35. increament BY 1
  36. *
  37. 2행에 오류:
  38. ORA-00933: SQL 명령어가 올바르게 종료되지 않았습니다
  39.  
  40.  
  41. SQL> c /increament BY 1/increment BY 1
  42. 2* increment BY 1
  43. SQL> run
  44. 1 CREATE sequence seq_iii
  45. 2 increment BY 1 -- 1단위로 증가함
  46. 3 start WITH 50 -- 50부터 시작하는 시퀀스
  47. 4 maxvalue 100 -- 최대값 100
  48. 5 nocache
  49. 6* nocycle
  50.  
  51. 주문번호가 생성되었습니다.
  52.  
  53. SQL> SELECT seq_iii.NEXTVAL FROM dual;
  54.  
  55. NEXTVAL
  56. ----------
  57. 50
  58.  
  59. SQL> SELECT seq_iii.currval FROM dual;
  60.  
  61. CURRVAL
  62. ----------
  63. 50
  64.  
  65. SQL> CREATE TABLE seq_test (id number);
  66.  
  67. 테이블이 생성되었습니다.
  68.  
  69. SQL> CREATE TABLE seq_test (id number);
  70.  
  71. 테이블이 생성되었습니다.
  72.  
  73. SQL> INSERT INTO seq_test VALUES (seq_iii.NEXTVAL);
  74.  
  75. 1 개의 행이 만들어졌습니다.
  76.  
  77. SQL> SELECT * FROM seq_test;
  78.  
  79. ID
  80. ----------
  81. 51
  82. SQL> -- 테이블 생성시 컬럼에 기본값을 설정해줬다면 INSERT시 다음과 같이 하면됨
  83.  
  84. SQL> ALTER TABLE STUDENT
  85. 2 ADD APPLY DATE DEFAULT SYSDATE;
  86.  
  87. 테이블이 변경되었습니다.
  88.  
  89. SQL> INSERT INTO STUDENT
  90. 2 VALUES ('9655023', '엄성재', '0164506701', DEFAULT);
  91.  
  92. 1 개의 행이 만들어졌습니다.
  93.  
  94. SQL> -- APPLY 컬럼에 기본값으로 현재 시스템의 날짜를 적용
  95. SQL> SELECT * FROM STUDENT
  96. 2 WHERE S_NUM = '9655023';
  97.  
  98. S_NUM S_NAME S_PHONE APPLY
  99. ------- -------- ----------- --------
  100. 9655023 엄성재 0164506701 02/05/19
  101.  
  102. SQL> -- DEFAULT 라는 키워드로 기본값이 들어감을 명시해 주지 않아도 기본값이 들어간다.
  103. SQL> INSERT INTO STUDENT(S_NUM, S_NAME, S_PHONE)
  104. 2 VALUES ('9555037', '전호중', '0172204580');
  105.  
  106. 1 개의 행이 만들어졌습니다.
  107.  
  108. SQL> SELECT * FROM STUDENT
  109. 2 WHERE S_NUM = '9555037';
  110.  
  111. S_NUM S_NAME S_PHONE APPLY
  112. ------- -------- ----------- --------
  113. 9555037 전호중 0172204580 02/05/19
  114.  
  115.  
  116. 시퀀스의 변경은 모두 생성문법과 같은데 start WITH문이 없다는 것 뿐입니다. 즉, 이미 생성
  117. 당시 시작할 시퀀스의 값이 정해졌기 때문입니다. 삭제는 DROP sequence sequence_name 을 하
  118. 면 됩니다.
  119.  
  120.  
  121. 이제 기본적인 INSERT 문의 사용법을 알았습니다. 상당히 간단하죠? 이제 SELECT 문과 합쳐진
  122. INSERT 문을 실습해보도록 하겠습니다. 먼저 테이블을 하나 생성합니다.
  123.  
  124.  
  125.  
  126. SQL> CREATE TABLE TEMP
  127. 2 (EMPNO NUMBER(4) PRIMARY KEY,
  128. 3 ENAME VARCHAR2(10),
  129. 4 JOB VARCHAR2(9),
  130. 5 MGR NUMBER(4),
  131. 6 HIREDATE DATE,
  132. 7 SAL NUMBER(7,2),
  133. 8 COMM NUMBER(7,2),
  134. 9 DEPTNO NUMBER(2));
  135.  
  136. 테이블이 생성되었습니다.
  137.  
  138.  
  139.  
  140.  
  141.  
  142. SQL> INSERT INTO TEMP
  143. 2 SELECT * FROM EMP
  144. 3 WHERE DEPTNO = 20;
  145.  
  146. 5 개의 행이 만들어졌습니다.
  147.  
  148. SQL> SELECT * FROM TEMP;
  149.  
  150. EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
  151. ---------- ---------- --------- ---------- -------- ---------- ---------- ----------
  152. 7369 SMITH CLERK 7902 80/12/17 800 20
  153. 7566 JONES MANAGER 7839 81/04/02 2975 20
  154. 7788 SCOTT ANALYST 7566 87/04/19 3000 20
  155. 7876 ADAMS CLERK 7788 87/05/23 1100 20
  156. 7902 FORD ANALYST 7566 81/12/03 3000 20
  157.  
  158. SQL> -- 이런 방법도 있지용~
  159. SQL> CREATE TABLE TEMP2
  160. 2 AS
  161. 3 SELECT * FROM EMP
  162. 4 WHERE DEPTNO = 10;
  163.  
  164. 테이블이 생성되었습니다.
  165.  
  166. SQL> SELECT * FROM TEMP2;
  167.  
  168. EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
  169. ---------- ---------- --------- ---------- -------- ---------- ---------- ----------
  170. 7782 CLARK MANAGER 7839 81/06/09 2450 10
  171. 7839 KING PRESIDENT 81/11/17 5000 10
  172. 7934 MILLER CLERK 7782 82/01/23 1300 10
  173. 1111 MILLER CLE%RK 7782 82/01/23 1300 10
  174.  
  175.  
  176.  
  177. 이렇게 SELECT 문을 이용해서도 INSERT를 할 수 있습니다. 좀더 복잡한 쿼리문을 써서도 삽입
  178. 을 할 수 있겠지요.
  179.  
* IE���� �ҽ� ����� �ٹٲ� �ȵ�. MS-Word � �ٿ� ��������. �ٹٲ� �Ǵ� ������: Chrome, Opera, Safari




3 UPDATE #

  1. UPDATE는 원래의 뜻과 같이 변경된 값을 적용하는 것을 의미합니다. UPDATE는 INSERT의 개념
  2. 을 가지고 있습니다. 여러분이 연필로 노트에 적고 고칠때는 어떻게 하나요? 지우개로 지운고
  3. 그 다음에 다시 변경된 사항을 적어 넣습니다. 일반적인 UPDATE 문법은 다음과 같습니다.
  4.  
  5.  
  6.  
  7. UPDATE TABLE_NAME
  8. SET COLUMN_NAME = VALUE
  9. WHERE CONDITION...
  10.  
  11.  
  12.  
  13. 실습을 통해서 익혀보도록 하겠습니다.
  14.  
  15.  
  16.  
  17. SQL> UPDATE TEMP
  18. 2 SET SAL = 1000
  19. 3 WHERE EMPNO = 7369;
  20.  
  21. 1 행이 갱신되었습니다.
  22.  
  23. SQL> SELECT EMPNO, SAL FROM TEMP
  24. 2 WHERE EMPNO = 7369;
  25.  
  26. EMPNO SAL
  27. ---------- ----------
  28. 7369 1000
  29.  
  30. SQL> -- 만약 SAL(월급)에서 세금(월급의 10%)을 제외한 실수령액으로 변경한다면?
  31. SQL> UPDATE TEMP
  32. 2 SET SAL = SAL - (SAL*0.1);
  33.  
  34. 5 행이 갱신되었습니다.
  35.  
  36. SQL> SELECT EMPNO, SAL FROM TEMP;
  37.  
  38. EMPNO SAL
  39. ---------- ----------
  40. 7369 900
  41. 7566 2677.5
  42. 7788 2700
  43. 7876 990
  44. 7902 2700
  45.  
  46. SQL> COMMIT;
  47.  
  48. 커밋이 완료되었습니다.
  49.  
  50.  
  51.  
  52. UPDATE의 기본적인 사용은 이렇습니다. 이번에는 쿼리를 이용한 약간은 복잡한 UPDATE문을 보
  53. 도록 하겠습니다.
  54.  
  55.  
  56.  
  57. SQL> SELECT EMPNO, SAL FROM TEMP;
  58.  
  59. EMPNO SAL
  60. ---------- ----------
  61. 7369 900
  62. 7566 2677.5
  63. 7788 2700
  64. 7876 990
  65. 7902 2700
  66.  
  67. SQL> SELECT AVG(SAL) FROM EMP;
  68.  
  69. AVG(SAL)
  70. ----------
  71. 2021.66667
  72.  
  73. SQL> -- EMP에서 사원의 평균월급보다 적은 TEMP 테이블의 SAL을 평균으로 고친다.
  74.  
  75. SQL> UPDATE TEMP
  76. 2 SET SAL = (SELECT AVG(SAL) FROM EMP)
  77. 3 WHERE SAL < (SELECT AVG(EMP.SAL)
  78. 4 FROM EMP, TEMP
  79. 5 WHERE EMP.EMPNO = TEMP.EMPNO);
  80.  
  81. 2 행이 갱신되었습니다.
  82.  
  83. SQL> SELECT EMPNO, SAL FROM TEMP;
  84.  
  85. EMPNO SAL
  86. ---------- ----------
  87. 7369 2021.67 -- 갱신된 행
  88. 7566 2677.5
  89. 7788 2700
  90. 7876 2021.67 -- 갱신된 행
  91. 7902 2700
  92.  
  93. SQL> COMMIT;
  94.  
  95. 커밋이 완료되었습니다.
  96.  
* IE���� �ҽ� ����� �ٹٲ� �ȵ�. MS-Word � �ٿ� ��������. �ٹٲ� �Ǵ� ������: Chrome, Opera, Safari




4 DELETE #

  1. DELETE는 테이블의 데이타 행을 삭제하는 것입니다. 필자는 DROP과 DELETE가 처음에 무진장
  2. 헤깔렸습니다. DROP은 객체(테이블, 인덱스, 시퀀스등)를 삭제하는 것이고, DELETE는 데이타
  3. 의 행을 삭제하는 것입니다. 혼동하지 마시길 바랍니다. 역시 실습을 통해서 알아보도록 하겠
  4. 습니다.
  5.  
  6.  
  7.  
  8. DELETE table_name
  9. WHERE condition
  10.  
  11.  
  12.  
  13.  
  14.  
  15. SQL> -- 모든 데이타행의 삭제
  16. SQL> DELETE TEMP;
  17.  
  18. 5 행이 삭제되었습니다.
  19.  
  20. SQL> SELECT COUNT(*) FROM TEMP;
  21.  
  22. COUNT(*)
  23. ----------
  24. 0
  25.  
  26. SQL> ROLLBACK;
  27.  
  28. 롤백이 완료되었습니다.
  29.  
  30. SQL> SELECT COUNT(*) FROM TEMP;
  31.  
  32. COUNT(*)
  33. ----------
  34. 5
  35.  
  36. SQL> -- EMPNO 가 7788 인 사원을 삭제
  37. SQL> DELETE TEMP
  38. 2 WHERE EMPNO = 7788;
  39.  
  40. 1 행이 삭제되었습니다.
  41.  
  42. SQL> COMMIT;
  43.  
  44. 커밋이 완료되었습니다.
  45.  
  46. SQL> -- 입사일이 80년에서 81년 사이인 사원을 삭제
  47. SQL> DELETE TEMP
  48. 2 WHERE HIREDATE BETWEEN '80/01/01' AND '81/12/31';
  49.  
  50. 3 행이 삭제되었습니다.
  51.  
  52. SQL> COMMIT;
  53.  
  54. 커밋이 완료되었습니다.
  55.  
  56. SQL> SELECT * FROM TEMP;
  57.  
  58. EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
  59. ---------- ---------- --------- ---------- -------- ---------- ---------- ----------
  60. 7876 ADAMS CLERK 7788 87/05/23 2021.67 20
  61.  
  62.  
  63.  
  64.  
* IE���� �ҽ� ����� �ٹٲ� �ȵ�. MS-Word � �ٿ� ��������. �ٹٲ� �Ǵ� ������: Chrome, Opera, Safari