카테고리 없음

Oracle 계층적 질의문과 import & export

JangGeonWu 2022. 8. 17. 12:09




계층적 질의문은 코딩테스트에도 쓰이니 잘 숙지해야 한다.
import랑 export는 글쎄... 그래도 숙지하면 언젠간 쓸 것 같다.


계층적 질의문

  • 관계형 DB에서, 데이터 간 부모 관계를 표현할 수 있는 칼럼을 지정해 계층적인 관계를 표현한다.
  • 셀프 조인과 유사하나 결이 다르다.

계층적 질의문은 SELECT문에서 START WITH와 CONNECT BY 절을 이용한다.

SELECT [LEVEL], COLs... -- LEVEL: 계층별로 레벨 표시, 루트는 1에서 시작해 1씩 증가
FROM table
WHERE condition
START WITH condition -- 계층적 출력 형식 표현
CONNECT BY PRIOR condition; -- 계층 관계의 데이터를 지정

CONNECT BY 절의 'PRIOR col1=col2'를 어떻게 정의하느냐에 따라 형식이 달라진다.

    1. top-down 형식
CONNECT BY PRIOR 자식_키 = 부모_키

      2. bottom-up 형식

CONNECT BY PRIOR 부모_키 = 자식_키

 

 

다음 예시를 통해 어떻게 쓰이는 지 알아보자.

SELECT  LEVEL, LPAD(' ',(LEVEL - 1) * 2) || dname as "조직도"
FROM    department
START WITH deptno = 10
CONNECT BY PRIOR deptno = college;
  • deptno는 부서 번호, college는 단과대학(번호)을 의미한다. 단과대학(번호)이 부서번호의 '부모 키'이므로, top-down 형식이라는 점을 알 수 있다.
  • START WITH deptno = 10은, 루트의 시작점의 조건을 의미한다. 즉, top에 해당하는 deptno = 10이라는 뜻.


    계층적 질의문을 DUAL에서 사용하는 방법
SELECT LEVEL-1 AS NUM -- 계층 레벨에 별명을 붙여 표현
FROM DUAL -- 테이블 DUAL에는 start 지점이 없다.
CONNECT BY LEVEL <= 24; -- 계층 관계가 없으므로 PRIOR가 붙지 않음, 조건절만 수행한다.
  • 위에서 중요하게 바라봐야 할 것은, CONNECT BY의 PRIOR는 뒤의 'condition'에 맞춰진다는 점이다.

예를 들면, 아래의 두 계층적 질의문은 결과가 달라진다.

-- 1번
SELECT  level, deptno, dname, college
FROM    department
START WITH deptno = 10
CONNECT BY dname != '정보미디어학부' AND prior deptno = college;
-- 2번
SELECT  level, deptno, dname, college
FROM    department
START WITH deptno = 10
CONNECT BY prior dname != '정보미디어학부' AND deptno = college;

위의 두 질의문 중 정답은 1번이다. 즉, prior는 두 column간의 부모-자식 관계를 구분할 때 쓰인다.


connect_by_root, connect_by_isleaf, connect_by_path

  • connect_by_root : level이 1인 최상위 로우의 '정보'를 얻어온다.
  • connect_by_isleaf : 해당 row의 최하위레벨(자식 노드가 없는 경우) 여부(False = 0, True = 1)를 반환한다.
  • connect_by_path : 로우의 path 정보를 반환한다.
-- connect_by_root: level이 1인 최상위 로우의 정보를 얻어올 수 있다.
SELECT LPAD(' ', 4*(level - 1)) || ename as "사원명",
    empno as "사번",
    CONNECT_BY_ROOT empno "최상위사번",
    LEVEL
FROM emp
START WITH job = UPPER('President')
CONNECT BY PRIOR empno = mgr;
-- connect_by_isleaf: 로우의 최하위레벨 '여부(False/True)'를 반환한다.
SELECT LPAD(' ', 4*(level - 1)) || ename as "사원명",
    empno as "사번",
    CONNECT_BY_ISLEAF Leaf_YN, -- 자신이 단말(leaf)인지 0,1로 표시
    LEVEL
FROM emp
START WITH job = UPPER('President')
CONNECT BY PRIOR empno = mgr;
-- SYS_CONNECT_BY_PATH: 로우의 path 정보를 반환한다.
SELECT LPAD(' ', 4*(level - 1)) || ename as "사원명",
    empno as "사번",
    SYS_CONNECT_BY_PATH(ename,'/') e_path, -- sys_connect_by_path는 함수이며, 경로를 칼럼과 입력한 특수문자로 표시한다,
    LEVEL
FROM emp
START WITH job = UPPER('President')
CONNECT BY PRIOR empno = mgr;

해당 변수는 조건절에 사용이 가능하다.

SELECT LPAD(' ', 4*(level - 1)) || ename as "사원명",
    empno as "사번",
    CONNECT_BY_ISLEAF Leaf_YN, -- 자신이 단말(leaf)인지 0,1로 표시
    LEVEL
FROM emp
WHERE connect_by_isleaf = 1 -- 단말인 row만 표시한다.
START WITH job = UPPER('President')
CONNECT BY PRIOR empno = mgr;

ORDER 'SIBLINGS' BY

  • 트리 구조는 그대로 두고, sibling 관계 내에서 정렬한다.

해석하자면, 다음 방식으로 order를 진행하면 트리 구조가 깨진다.

SELECT LPAD(' ', 4*(level - 1)) || ename as "사원명",
    empno as "사번",
    CONNECT_BY_ISLEAF Leaf_YN, -- 자신이 단말(leaf)인지 0,1로 표시
    LEVEL 
FROM emp
START WITH job = UPPER('President')
CONNECT BY PRIOR empno = mgr
ORDER BY ename; -- 트리 파괴

다음 방식으로 order를 진행해야 트리 구조가 유지된다.

SELECT LPAD(' ', 4*(level - 1)) || ename as "사원명",
    empno as "사번",
    CONNECT_BY_ISLEAF Leaf_YN, -- 자신이 단말(leaf)인지 0,1로 표시
    LEVEL
FROM emp
START WITH job = UPPER('President')
CONNECT BY PRIOR empno = mgr
ORDER SIBLINGS BY ename; -- 트리 유지

CYCLE 조건

  • connect_by_iscycle: 부모-자식간의 관계가 cycle을 만들면 1, 아니면 0을 반환한다.
  • CONNECT BY 절에 "NOCYCLE PRIOR"을 조건으로 '루프'를 무한하게 출력하는 상황을 방지할 수도 있다. 아래와 같이 말이다.
SELECT LPAD(' ', 4*(level - 1)) || ename as "사원명",
    empno as "사번",
    CONNECT_BY_ISLEAF Leaf_YN, -- 자신이 단말(leaf)인지 0,1로 표시
    LEVEL
FROM emp
START WITH job = UPPER('President')
CONNECT BY NOCYCLE PRIOR empno = mgr
ORDER SIBLINGS BY ename; -- 트리 유지

EXPORT and IMPORT

  • 데이터베이스 간 데이터 정보를 쉽게 이동시킬 수 있는 간단한 방법을 제공한다.

주로 다음과 같은 상황에서 쓰인다.

  • 테이블 재구성 할 때
  • Row Migration이 많이 발생한 경우
  • 빈 Block이 많은 경우
  • Fragmentation이 많이 발생한 경우
  • 경합을 최소화하기 위해서
  • 사용자간에 데이터를 이동하기 위해(사용자 계정을 제거하거나 정보 분배할 때)
  • 데이터베이스 간에 데이터를 이동하기 위해
  • 개발 데이터베이스에서 실제 서비스가 이루어지는 데이터베이스로 데이터를 이전할 때
  • 다른 플랫폼으로 데이터를 이전할 때
  • 데이터베이스 버전 변경을 위해서 '백업'할 때 등에 사용

어... 위에서 Row Migration이랑 Fragmentation, 경합의 최소화는 짧게 짚고 넘어가보자.

  1. Row Migration: update로 인해 행의 길이가 증가했을 때, 저장 공간이 부족한 경우에 원래 정보(주소)를 기존 블록에 남겨두고 실제 데이터를 다른 블록에 저장하는 경우를 의미.
  2. Fragmentation(단편화): insert와 update를 하다보면 테이블 스페이스에 '빈 공간'이 조금씩 생기는데, 이 '빈 공간'이 쌓이는 걸 단편화라고 한다.
  3. 경합의 최소화: 트랜잭션끼리 서로 충돌하는 걸 방지하기 위해 'lock(잠금)'이라는 걸 설정하는데, 이 'lock' 때문에 발생하는 문제를 '경합'이라 한다.

  • Export-Import 할 때 알아두어야 할 점이다.
  1. catexp.sql은 Export-Import를 하기 위한 뷰를 생성한다. 이는 일반적으로 database를 생성할 때 catalog.sql이라는 게 만들어지는데, 이 안에 포함되어있다.
  2. 공통적으로 사용되는 '파라미터'는 Parameter 파일에 지정한다. 파라미터는 따로 지정 안하면 나중에 문제 생길수도 있다.
  3. Export 하기 전, Disk 공간이 충분한 지 확인해야 한다. Export로 나오는 dmp 파일이 생각보다 크다는 걸 명심하자.

Export

일단, Export하기 전에 SQL에서 'HOST'를 입력한 뒤에 다음을 실행해야 한다. 이때,

cd C:\Users\user

으로 파일 생성하기를 원하는 곳으로 이동할 수 있다.
뭐 필수는 아닌데, 내 파일이 어딨는지는 알아야 하니까 :)

그러고서 다음 명령어를 입력하면 된다.

-- 1: system이 hr의 테이블 export
C:\Users\user>exp system/manager tables=(hr.emp, hr.dept) grants=y indexes=y

-- 2: hr 본인이 본인 테이블 export
C:\Users\user>exp hr/hr file=hr.dmp tables=(emp,dept) rows=y compress=y

-- 3: hr 본인이 본인 '데이터베이스' 전체를 export
C:\Users\user>exp hr/hr file=hr_all.dmp owner=hr grants=y rows=y compress=y

-- 4: system이 hr의 '데이터베이스' 전체를 export
C:\Users\user>exp system/manager full=y file=dba1.dmp grants=y rows=y

아래는 위의 파라미터들을 정리한 표이다.

파라미터 의미
exp export
aa/bb 유저/유저패스워드
file=aaa.dmp 저장할 dump 파일 이름
grants 객체에 대한 권한을 export 여부
indexes 인덱스 export 여부
log 모든 export 메시지를 기록할 파일 이름으로, 기록 안하면 log 생성 안함
direct 직접 경로로 export
rows 행(데이터)들이 export 될 것인지 여부
compress fragmentation된 세그먼트들을 압축할 지 여부
owner 사용자 객체와 데이터, owner의 모든 권한과 인덱스의 export 여부
full 전체 데이터베이스를 export할 지 여부




import

  • import도 export랑 비슷하다.

다음 명령어를 수행하면 된다.

-- 1: system이 hr의 테이블 import
C:\Users\user>imp system/manager file=EXPDAT.dmp fromuser=hr tables=(hr.emp, hr.dept)

-- 2: system이 hr의 테이블을 tiger에게 import
C:\Users\user>imp system/manager file=hr.dmp fromuser=hr touser=tiger tables=(emp,dept)

-- 3: system이 hr의 '데이터베이스' 전체를 tiger에게 import
C:\Users\user>imp system/manager file=hr_all.dmp fromuser=hr touser=tiger

아래는 위의 파라미터들을 정리한 표이다.

파라미터 의미
imp import
aa/bb 유저/유저패스워드
file=aaa.dmp import할 dump 파일 이름
show import 실행하는 대신 화면에 표시할 지 여부
ignore import하면서 발생하는 에러를 무시할 지 여부
grants 권한을 import할 지 여부
fromuser 읽을 객체들을 가지고 있는 사용자 목록
touser import를 적용할 대상(유저)
tables import할 테이블 목록




이것으로 계층적 질의문과 import, export에 대한 내용을 정리하였다.