DataBase

[오라클] connect by 개념 및 사용법

부지런한피로 2025. 4. 3. 14:07

1️⃣ CONNECT BY란?

Oracle의 CONNECT BY는 계층적 쿼리(Hierarchical Query) 를 실행할 때 사용되는 구문입니다.
계층 구조를 가진 데이터를 부모-자식 관계를 기준으로 트리 형태로 조회할 수 있도록 합니다.

📌 주로 사용되는 곳:

  • 조직도 (상사-부하 관계)
  • 카테고리 트리 (부모-자식 관계)
  • 제품 분류 구조
  • 메뉴 및 UI 네비게이션 구조

 

2️⃣ CONNECT BY의 기본 구문

SELECT 컬럼명
FROM 테이블명
START WITH 루트 조건
CONNECT BY PRIOR 부모_컬럼 = 자식_컬럼;
  • START WITH → 최상위 부모 노드(루트 노드)를 설정
  • CONNECT BY PRIOR 부모_컬럼 = 자식_컬럼 → 부모-자식 관계 정의

 

3️⃣ 예제: 직원 조직도 계층 구조 조회

📌 (1) 샘플 테이블 생성 및 데이터 삽입

CREATE TABLE employees (
    emp_id NUMBER PRIMARY KEY,  -- 직원 ID
    emp_name VARCHAR2(50),      -- 직원 이름
    manager_id NUMBER           -- 상사의 ID (최고 경영자는 NULL)
);

INSERT INTO employees VALUES (1, 'CEO', NULL);
INSERT INTO employees VALUES (2, 'Manager A', 1);
INSERT INTO employees VALUES (3, 'Manager B', 1);
INSERT INTO employees VALUES (4, 'Employee A1', 2);
INSERT INTO employees VALUES (5, 'Employee A2', 2);
INSERT INTO employees VALUES (6, 'Employee B1', 3);
INSERT INTO employees VALUES (7, 'Employee B2', 3);

COMMIT;

 

📌 조직도 구조

CEO (1)
 ├── Manager A (2)
 │    ├── Employee A1 (4)
 │    ├── Employee A2 (5)
 ├── Manager B (3)
      ├── Employee B1 (6)
      ├── Employee B2 (7)

 

 

📌 (2) CONNECT BY를 이용한 계층형 쿼리

SELECT LEVEL, emp_id, emp_name, manager_id
FROM employees
START WITH manager_id IS NULL
CONNECT BY PRIOR emp_id = manager_id;

📌 실행 결과

LEVEL | EMP_ID | EMP_NAME     | MANAGER_ID
-----------------------------------------
1     | 1      | CEO         | NULL
2     | 2      | Manager A   | 1
3     | 4      | Employee A1 | 2
3     | 5      | Employee A2 | 2
2     | 3      | Manager B   | 1
3     | 6      | Employee B1 | 3
3     | 7      | Employee B2 | 3

LEVEL 컬럼은 계층 레벨을 나타내며, 최상위 부모(CEO)는 LEVEL=1, 그 다음 레벨부터 차례로 증가합니다.

 

 

📌 (3) LPAD를 사용한 계층 구조 가시화

SELECT LPAD(' ', LEVEL * 2, ' ') || emp_name AS hierarchy, emp_id, manager_id
FROM employees
START WITH manager_id IS NULL
CONNECT BY PRIOR emp_id = manager_id;

📌 실행 결과

HIERARCHY        | EMP_ID | MANAGER_ID
-----------------------------------
CEO             | 1      | NULL
  Manager A     | 2      | 1
    Employee A1 | 4      | 2
    Employee A2 | 5      | 2
  Manager B     | 3      | 1
    Employee B1 | 6      | 3
    Employee B2 | 7      | 3

✅ LPAD(' ', LEVEL * 2, ' ') || emp_name 를 사용하여 들여쓰기로 계층 구조를 표현합니다.

 

 

4️⃣ CONNECT BY에서 SYS_CONNECT_BY_PATH 활용

계층 구조를 경로(Path) 형태로 출력할 수도 있습니다.

SELECT emp_id, emp_name, manager_id, SYS_CONNECT_BY_PATH(emp_name, ' -> ') AS path
FROM employees
START WITH manager_id IS NULL
CONNECT BY PRIOR emp_id = manager_id;

📌 실행 결과

EMP_ID | EMP_NAME     | MANAGER_ID | PATH
--------------------------------------------
1      | CEO         | NULL       |  -> CEO
2      | Manager A   | 1          |  -> CEO -> Manager A
4      | Employee A1 | 2          |  -> CEO -> Manager A -> Employee A1
5      | Employee A2 | 2          |  -> CEO -> Manager A -> Employee A2
3      | Manager B   | 1          |  -> CEO -> Manager B
6      | Employee B1 | 3          |  -> CEO -> Manager B -> Employee B1
7      | Employee B2 | 3          |  -> CEO -> Manager B -> Employee B2

✅ SYS_CONNECT_BY_PATH(컬럼명, 구분자)를 이용하면 전체 경로(Path) 를 출력할 수 있습니다.

 

 

5️⃣ CONNECT BY에서 ORDER SIBLINGS BY 활용 (계층 정렬)

ORDER SIBLINGS BY를 사용하면 같은 레벨 내에서 특정 컬럼을 기준으로 정렬할 수 있습니다.

SELECT LEVEL, emp_id, emp_name, manager_id
FROM employees
START WITH manager_id IS NULL
CONNECT BY PRIOR emp_id = manager_id
ORDER SIBLINGS BY emp_name;

 

✅ 같은 레벨(부서 내)에서는 emp_name 기준으로 알파벳 순 정렬됩니다.

 

 

6️⃣ CONNECT BY에서 순환 참조(Loop) 방지 방법

계층 구조에서 부모-자식 관계가 순환 구조(Loop)가 되면 무한 루프에 빠질 수 있습니다.
이런 문제를 방지하려면 NOCYCLE 옵션을 사용합니다.

SELECT emp_id, emp_name, manager_id
FROM employees
START WITH manager_id IS NULL
CONNECT BY NOCYCLE PRIOR emp_id = manager_id;

✅ NOCYCLE 옵션을 사용하면 순환 관계(Loop)가 감지될 경우 즉시 중단합니다.

 

 

7️⃣ CONNECT BY 요약 정리

기능 설명 예제
START WITH 루트 노드(최상위 부모)를 지정 START WITH manager_id IS NULL
CONNECT BY PRIOR 부모-자식 관계 정의 CONNECT BY PRIOR emp_id = manager_id
LEVEL 계층 구조의 깊이를 나타냄 SELECT LEVEL FROM employees
SYS_CONNECT_BY_PATH 전체 경로 출력 SYS_CONNECT_BY_PATH(emp_name, ' -> ')
ORDER SIBLINGS BY 계층 내에서 정렬 ORDER SIBLINGS BY emp_name
NOCYCLE 순환 참조 방지 CONNECT BY NOCYCLE PRIOR emp_id = manager_id

 

 

8️⃣ 결론

  • CONNECT BY는 계층형 데이터(부모-자식 관계)를 다룰 때 필수적인 기능
  • LEVEL, SYS_CONNECT_BY_PATH, ORDER SIBLINGS BY 등을 조합하면 더욱 강력한 계층 쿼리를 작성 가능
  • 순환 참조 문제를 방지하려면 NOCYCLE을 사용해야 함

트리 구조 데이터 조회가 필요할 때 CONNECT BY를 활용하면 SQL 하나로 쉽게 해결 가능! 🚀