TOOL/DATABASE 2017. 9. 29. 14:05

!markdown



# Oracle (오라클)


`계층구조`의 테이블의 데이터를 파악하고 싶다면, 오라클의 다음 문법을 사용해보자. `Oracle 8i`부터 지원한다고 하니 `호환성`도 좋다.

- START WITH

- CONNECT BY PRIOR






## 계층형 구조 쿼리 만들기


### 1. 테스트 데이터


설명하기에 앞서서 Oracle의 `DUAL`을 이용하여 다음과 같이 `테스트 데이터`를 만들었다.


아이디 값(`THIS_ID`)과 이름(`THIS_NAME`) 그리고 나를 포함하고 있는 상위의 아이디(`PARENT_ID`)까지 컬럼이 3개인 가상 테이블을 만들어서 테스트해 보자.


```sql

--------------------

-- 테스트 데이터

--------------------

      SELECT 0 as THIS_ID,   '루트' as THIS_NAME,   null PARENT_ID FROM DUAL

        UNION

      SELECT 1 as THIS_ID,   '1뎁스-1' as THIS_NAME,   0 PARENT_ID FROM DUAL

        UNION

      SELECT 2 as THIS_ID,   '1뎁스-2' as THIS_NAME,   0 PARENT_ID FROM DUAL

        UNION

      SELECT 3 as THIS_ID,   '2뎁스-1' as THIS_NAME,   1 PARENT_ID FROM DUAL

        UNION

      SELECT 4 as THIS_ID,   '2뎁스-2' as THIS_NAME,   1 PARENT_ID FROM DUAL

        UNION

      SELECT 5 as THIS_ID,   '2뎁스-3' as THIS_NAME,   2 PARENT_ID FROM DUAL

```




### 2. START WITH와 CONNECT BY PRIOR


`START WITH`와 `CONNECT BY PRIOR`를 설정하면 각 ROW마다 `계층구조를 알수 있는 데이터`를 활용할 수 있다.


더불어서 `LEVEL`컬럼의 값을 사용할 수 있는데, 이를 활용하면 `계층깊이 만큼의 수치`를 얻을 수 있다.


```sql

--------------------

-- 모든 계층구조 파악하기

--------------------

SELECT  THIS_ID,

            PARENT_ID,

            LEVEL,

            LPAD(' └', 2*(LEVEL-1)) || THIS_NAME CONTAINER_NAME_IMAGE

FROM (

      SELECT 0 as THIS_ID,   '루트' as THIS_NAME,   null PARENT_ID FROM DUAL

        UNION

      SELECT 1 as THIS_ID,   '1뎁스-1' as THIS_NAME,   0 PARENT_ID FROM DUAL

        UNION

      SELECT 2 as THIS_ID,   '1뎁스-2' as THIS_NAME,   0 PARENT_ID FROM DUAL

        UNION

      SELECT 3 as THIS_ID,   '2뎁스-1' as THIS_NAME,   1 PARENT_ID FROM DUAL

        UNION

      SELECT 4 as THIS_ID,   '2뎁스-2' as THIS_NAME,   1 PARENT_ID FROM DUAL

        UNION

      SELECT 5 as THIS_ID,   '2뎁스-3' as THIS_NAME,   2 PARENT_ID FROM DUAL

) TEST_DATA

START WITH PARENT_ID IS NULL

CONNECT BY PRIOR THIS_ID = PARENT_ID

```




### 3. CONNECT_BY_ROOT


`CONNECT_BY_ROOT`를 이용하면 해당 ROW마다 `가장 최상위 계층의 데이터`(ROOT 데이터)를 활용할 수 있다.


```sql

--------------------

-- 모든 계층구조 파악하기

-- - 항목별로 루트정보도 포함

--------------------

SELECT  THIS_ID,

           PARENT_ID,

           LEVEL,

           LPAD(' └', 2*(LEVEL-1)) || THIS_NAME CONTAINER_NAME_IMAGE,

           CONNECT_BY_ROOT THIS_ID      AS ROOT_ID,

           CONNECT_BY_ROOT THIS_NAME    AS ROOT_NAME

FROM (

      SELECT 0 as THIS_ID,   '루트' as THIS_NAME,   null PARENT_ID FROM DUAL

        UNION

      SELECT 1 as THIS_ID,   '1뎁스-1' as THIS_NAME,   0 PARENT_ID FROM DUAL

        UNION

      SELECT 2 as THIS_ID,   '1뎁스-2' as THIS_NAME,   0 PARENT_ID FROM DUAL

        UNION

      SELECT 3 as THIS_ID,   '2뎁스-1' as THIS_NAME,   1 PARENT_ID FROM DUAL

        UNION

      SELECT 4 as THIS_ID,   '2뎁스-2' as THIS_NAME,   1 PARENT_ID FROM DUAL

        UNION

      SELECT 5 as THIS_ID,   '2뎁스-3' as THIS_NAME,   2 PARENT_ID FROM DUAL

) TEST_DATA

START WITH PARENT_ID IS NULL

CONNECT BY PRIOR THIS_ID = PARENT_ID

```


그 밖에도 다음을 활용할 수 있다.




### 4. CONNECT_BY_ISLEAF


`CONNECT_BY_ISLEAF`를 이용하여 자식ROW 존재 여부




### 5. CONNECT_BY_ISCYCLE


`CONNECT_BY_ISCYCLE`를 이용하여 계층구조가 다시 자신에게 돌아오는 무한 뺑뺑이(?) 구조인지 여부




### 6. SYS_CONNECT_BY_PATH


`SYS_CONNECT_BY_PATH`를 이용하여 파일시스템 폴더 구조처럼 출력




### 참고


- [오라클] 계층형 쿼리 ( START WITH ... CONNECT BY ): [https://m.blog.naver.com/PostView.nhn?blogId=javaking75&logNo=220010288704&proxyReferer=https%3A%2F%2Fwww.google.co.kr%2F](https://m.blog.naver.com/PostView.nhn?blogId=javaking75&logNo=220010288704&proxyReferer=https%3A%2F%2Fwww.google.co.kr%2F)


- [oracle] CONNECT_BY_ROOT - 최상위 루트노드 찾기: [http://devjhs.tistory.com/166](http://devjhs.tistory.com/166)