Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
SQL Server 2008에서는 계층 구조형 데이터를 지원하기 위한 HierarchyID 데이터 타입을 지원합니다.
HierarchyID 데이터 타입을 이용하면 기존 SQL Server 2000의 재귀 쿼리 및 2005의 CTE (공통 테이블 식)을 이용하는 것 보다 훨씬 편하게 조직도 등의 계층 구조를 표현할 수 있습니다. (해당 내용은 BOL에서도 확인하실 수 있습니다.)
- GetAncestor, GetDescendant, GetLevel, GetRoot, IsDescendantOf 등 다양한 메소드를 통해 쉽게 계층구조 쿼리를 할 수 있습니다.
- 깊이 우선 인덱스 (Depth-first Index) 및 너비 우선 인덱스 (Breadth-First Index) 지원하여 쿼리 성능을 보장합니다.
그럼 간단하게 HierarchyID를 사용하여 계층구조를 표현해 보도록 하겠습니다.
전체적인 조직도는 아래와 같이 출력해보려 합니다.
/************************************
David (Marketing Manager)└ Sariya (Marketing Specialist)
└ Wanida (Marketing Assistant)└ John (Marketing Specialist)
└ Mary (Marketing Assistant)└ Jill (Marketing Specialist)
************************************/
우선 아래와 같이 테스트를 위한 샘플 테이블 및 인덱스를 생성합니다.
-- HierarchyID 데이터 타입을 사용하는 테이블 작성
CREATE TABLE HumanResources.EmployeeOrg
(
OrgNode hierarchyid PRIMARY KEY CLUSTERED,
EmployeeID int UNIQUE NOT NULL,
EmpName varchar(20) NOT NULL,
Title varchar(20) NULL
) ;
GO-- 깊이 우선 인덱스 생성 (depth-first index)
CREATE UNIQUE INDEX EmployeeOrgNc1
ON HumanResources.EmployeeOrg(OrgNode) ;
GO
이제 테스트를 위한 샘플 데이터를 테이블에 넣으려 하는데요, Root 데이터를 INSERT하고 나머지 데이터는 프로시저를 만들어서 넣도록 하겠습니다.
-- Root 데이터(David, Marketing Manager) 추가
INSERT HumanResources.EmployeeOrg (OrgNode, EmployeeID, EmpName, Title)
VALUES (hierarchyid::GetRoot() , 6, 'David', 'Marketing Manager') ;
GO-- 직원을 추가하기 위한 프로시저 생성 (파라미터 : Manager ID, 직원 ID, 이름, 직책)
CREATE PROC AddEmp(@mgrid int, @empid int, @e_name varchar(20), @title varchar(20))
AS
BEGIN
DECLARE @mOrgNode hierarchyid, @lc hierarchyid
SELECT @mOrgNode = OrgNode
FROM HumanResources.EmployeeOrg
WHERE EmployeeID = @mgrid
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION
SELECT @lc = max(OrgNode)
FROM HumanResources.EmployeeOrg
WHERE OrgNode.GetAncestor(1) =@mOrgNode ;INSERT HumanResources.EmployeeOrg (OrgNode, EmployeeID, EmpName, Title)
VALUES(@mOrgNode.GetDescendant(@lc, NULL), @empid, @e_name, @title)
COMMIT
END ;
GO-- 프로시저를 이용하여 David를 Manager(Parent Node)로 하는 직원 추가
EXEC AddEmp 6, 46, 'Sariya', 'Marketing Specialist' ;
EXEC AddEmp 6, 271, 'John', 'Marketing Specialist' ;
EXEC AddEmp 6, 119, 'Jill', 'Marketing Specialist' ;-- 프로시저를 이용하여 Sariya를 Manager(Parent Node)로 하는 직원 추가
EXEC AddEmp 46, 269, 'Wanida', 'Marketing Assistant' ;-- 프로시저를 이용하여 John을 Manager(Parent Node)로 하는 직원 추가
EXEC AddEmp 271, 272, 'Mary', 'Marketing Assistant'
데이터를 넣은 후 SELECT 문을 이용해 전체 계층 구조를 쿼리해 보면 아래와 같이 결과를 얻을 수 있습니다.
-- 전체 조직도 출력
SELECT OrgNode.ToString() AS Text_OrgNode,
OrgNode, EmployeeID, EmpName, Title
FROM dbo.EmployeeOrg ;
만약 조직도 내에서 각 직원의 조직 내 레벨을 출력하고 싶을 경우엔 GetLevel() 함수를 사용하여 쉽게 출력 가능합니다.
-- 각 직원별 조직도에서의 레벨을 포함하여 출력
SELECT OrgNode.ToString() AS Text_OrgNode,
OrgNode.GetLevel() AS EmpLevel, *
FROM dbo.EmployeeOrg ;
GO
특정 직원의 부모 노드를 Root노드 까지 모두 출력해 보고 싶을 경우엔 IsDescendantOf() 함수를 이용할 수 있습니다.
-- 특정 직원의 부모 노드(Root까지)를 모두 출력
DECLARE @CurrentEmployee hierarchyid
SELECT @CurrentEmployee = OrgNode
FROM dbo.EmployeeOrg
WHERE EmployeeID = 269 ;SELECT *
FROM dbo.EmployeeOrg
WHERE @CurrentEmployee.IsDescendantOf(OrgNode) = 1 ;
이렇듯 SQL Server 2008의 HierarchyID 데이터 타입을 이용하면, 저 처럼 재귀처리에 꽝(?!)인 사람도 쉽게 조직도 및 계층도 등을 구현할 수 있습니다.
많이 많이 이용해주세요~ :)