본문으로 이동
메뉴 여닫기
환경 설정 메뉴 여닫기
개인 메뉴 여닫기
로그인하지 않음
지금 편집한다면 당신의 IP 주소가 공개될 수 있습니다.
Identifier
엔터티 안에서 인스턴스 하나하나를 구별해 주는 속성 또는 속성의 조합

데이터 모델링에서 식별자(Identifier)는 엔터티에 속한 인스턴스를 서로 구별하는 구분자다. 논리 모델의 식별자는 물리 모델에서 키로 구현된다. 주식별자는 기본키(PK), 보조식별자는 UNIQUE 제약이 걸린 대체키가 되는 것이 보통이다.

이 문서는 데이터 모델의 식별자를 다룬다. 개인을 알아볼 수 있는 정보로서의 식별자는 식별자 문서를 참고한다.

주식별자의 특징

편집 원본 편집
특징 설명 맞지 않는 예
유일성 주식별자로 엔터티의 모든 인스턴스를 유일하게 구별할 수 있어야 한다. 사원 엔터티의 '이름': 동명이인이 있으면 구별하지 못한다.
최소성 주식별자를 이루는 속성 수는 유일성을 만족하는 최소 수여야 한다. (사번, 이름): 사번만으로 유일하므로 이름은 불필요하다.
불변성 주식별자 값은 한 번 정해지면 바뀌지 않아야 한다. '휴대전화번호': 번호를 바꾸면 식별자가 바뀌어 참조하던 데이터를 모두 고쳐야 한다.
존재성 주식별자로 지정되면 반드시 값이 있어야 한다(NULL 불가). '이메일'을 주식별자로 두었는데 이메일이 없는 고객이 있는 경우

식별자의 분류

편집 원본 편집

SQLD 출제 범위에서 쓰는 분류다. 하나의 식별자는 네 기준에서 각각 하나씩의 성격을 가진다.

분류 기준 식별자 설명 예
대표성 여부 주식별자 인스턴스를 유일하게 구별하며, 다른 엔터티와 참조 관계를 연결할 수 있는 식별자 사원의 사번
보조식별자 인스턴스를 유일하게 구별할 수는 있지만 대표 식별자가 아니어서 참조 관계 연결에 쓰지 않는 식별자 사원의 주민등록번호
스스로 생성 여부 내부식별자 엔터티 내부에서 스스로 만들어지는 식별자 고객번호
외부식별자 다른 엔터티와의 관계를 통해 넘어온 식별자 주문 엔터티의 고객번호(FK)
속성의 수 단일식별자 하나의 속성으로 이루어진 식별자 사번
복합식별자 둘 이상의 속성으로 이루어진 식별자 주문상세의 (주문번호, 순번)
대체 여부 본질식별자 업무에 의해 만들어지는 식별자 주문번호 + 상품번호
인조식별자 업무적으로 만들어지지는 않지만 원래 식별자가 복잡해 인위적으로 만든 식별자 주문상세번호(일련번호)

주식별자 도출 기준

편집 원본 편집
  • 해당 업무에서 자주 이용되는 속성을 주식별자로 지정한다. 예를 들어 학번과 주민등록번호가 모두 유일하다면 학사 업무에서 늘 쓰는 학번을 주식별자로, 주민등록번호를 보조식별자로 둔다.
  • 명칭이나 내역처럼 이름으로 기술되는 속성은 주식별자로 지정하지 않는다. '부서명'은 같은 이름이 생길 수 있고 바뀌기도 하므로 '부서코드'를 따로 둔다.
  • 복합식별자를 구성하는 속성 수가 너무 많으면, 조회 조건과 조인 조건이 길어지므로 인조식별자를 만들어 주식별자로 쓰는 것을 검토한다.
모델링 용어 관계형 모델·DB 용어 설명
주식별자 기본키(PK) 후보키 중에서 고른 대표 키
보조식별자 대체키 기본키로 고르지 않은 나머지 후보키. UNIQUE 제약으로 구현한다.
주식별자·보조식별자 후보 후보키 유일성과 최소성을 모두 만족하는 속성 집합
(해당 없음) 슈퍼키 유일성만 만족하는 속성 집합. 최소성은 따지지 않는다.
외부식별자 외래키(FK) 다른 테이블의 키를 참조하는 칼럼

식별 관계와 비식별 관계

편집 원본 편집

부모 엔터티의 주식별자가 자식 엔터티로 넘어갈 때, 그것이 자식의 주식별자에 포함되는지에 따라 관계를 나눈다. 관계의 일반적인 종류는 데이터베이스 관계 유형 문서를 참고한다.

구분 식별 관계(Identifying Relationship) 비식별 관계(Non-Identifying Relationship)
부모 PK의 위치 자식의 PK에 포함된다. 자식의 일반 속성(FK)이 된다.
관계의 강도 강한 연결. 부모 없이 자식이 존재할 수 없다. 약한 연결. 부모와 별개로 자식을 식별한다.
ERD 표기(IE) 실선 점선
예 주문 → 주문상세(PK: 주문번호, 순번) 부서 → 사원(PK: 사번, FK: 부서코드)

식별 관계만 쓸 때의 문제

편집 원본 편집

식별 관계로만 이어 가면 부모의 PK가 자식, 손자, 증손자로 계속 내려가며 PK 속성 수가 늘어난다. 예를 들어 회사 → 부서 → 팀 → 사원을 모두 식별 관계로 연결하면 사원의 PK가 (회사코드, 부서코드, 팀코드, 사원번호)가 된다. PK가 길어지면 조인 조건과 WHERE 조건이 복잡해지고, 실수로 일부 조건을 빠뜨리기 쉽다.

비식별 관계만 쓸 때의 문제

편집 원본 편집

비식별 관계로만 연결하면 부모의 키 값이 자식 PK에 없으므로, 상위 엔터티의 속성으로 조회하려면 중간 엔터티를 거쳐 조인해야 한다. 위 예에서 '회사코드별 사원 수'를 구하려면 사원 → 팀 → 부서까지 조인해야 할 수 있어 SQL이 길어지고 성능이 떨어질 수 있다.

비식별 관계를 선택하는 경우

편집 원본 편집
  • 부모와 자식의 관계가 약한 경우(자식이 부모에 강하게 종속되지 않는 경우)
  • 자식 엔터티가 독립적인 주식별자를 가져야 하는 경우
  • 식별 관계로 하면 자식의 PK 속성이 너무 많아지는 경우
  • 부모 없이도 자식 인스턴스가 생성될 수 있는 경우(FK가 NULL을 허용하는 선택 관계)

본질식별자와 인조식별자

편집 원본 편집
  • 본질식별자는 업무에 의해 자연스럽게 만들어지는 식별자다. 예를 들어 주문상세는 '어느 주문(주문번호)에서 어느 상품(상품번호)을 샀는가'로 식별된다.
  • 인조식별자는 업무와 무관하게 인위적으로 만든 식별자다. 일련번호, 시퀀스, IDENTITY 칼럼으로 값을 자동 생성하는 경우가 대표적이다. 위 예라면 주문상세번호(1, 2, 3, …)를 PK로 둔다.
구분 내용
장점 PK가 단일 속성이 되어 단순해진다. 자식 엔터티로 넘어가는 FK도 짧아지고, 본질식별자가 바뀌어도 PK는 영향을 받지 않는다.
단점 1 같은 업무 데이터가 중복 저장될 수 있다. 일련번호는 매번 새로 생기므로 PK 제약만으로는 같은 내용의 행을 막지 못한다.
단점 2 불필요한 인덱스가 늘어난다. 업무 조회는 여전히 본질 속성으로 하므로 PK 인덱스와 별도로 본질 속성 인덱스(UNIQUE 제약)가 하나 더 필요하다.

오라클 예: 인조식별자와 중복 데이터

편집 원본 편집

회원 엔터티의 본질 식별 속성은 이메일이고, 인조식별자 회원번호를 PK로 둔 경우다. 오라클 12c부터 GENERATED AS IDENTITY로 자동 번호를 만들 수 있다.

CREATE TABLE 회원 (
  회원번호 NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  이메일   VARCHAR2(50) NOT NULL,
  이름     VARCHAR2(20) NOT NULL
);
INSERT INTO 회원 (이메일, 이름) VALUES ('[email protected]', '김철수');
INSERT INTO 회원 (이메일, 이름) VALUES ('[email protected]', '김철수');   -- 같은 회원이 또 들어간다
SELECT 회원번호, 이메일, 이름 FROM 회원 ORDER BY 회원번호;
회원번호 이메일 이름
1 [email protected] 김철수
2 [email protected] 김철수

PK는 1과 2로 서로 다르므로 PK 제약은 아무 문제를 보지 못한다. 업무 관점에서는 같은 회원이 두 번 등록된 중복 데이터다. 해결책은 본질 식별 속성에 UNIQUE 제약을 거는 것이다. 이미 중복이 있으면 제약을 만들 수 없으므로 먼저 정리한다.

ALTER TABLE 회원 ADD CONSTRAINT 회원_이메일_UK UNIQUE (이메일);
-- ORA-02299: 중복 키가 있어 제약을 검증할 수 없음

DELETE FROM 회원 WHERE 회원번호 = 2;
ALTER TABLE 회원 ADD CONSTRAINT 회원_이메일_UK UNIQUE (이메일);   -- 성공

INSERT INTO 회원 (이메일, 이름) VALUES ('[email protected]', '김철수');
-- ORA-00001: 회원_이메일_UK 위반, 중복 등록이 막힌다
INSERT INTO 회원 (이메일, 이름) VALUES ('[email protected]', '이영희');
SELECT 회원번호, 이메일, 이름 FROM 회원 ORDER BY 회원번호;
회원번호 이메일 이름
1 [email protected] 김철수
4 [email protected] 이영희
  • 이영희의 회원번호가 3이 아니라 4다. 실패한 INSERT에서도 IDENTITY 번호가 소비되었기 때문이다. 인조식별자 값에는 빈 번호가 생길 수 있으므로 업무적 의미(건수 등)를 부여하면 안 된다.
  • UNIQUE 제약을 추가하자 테이블의 인덱스가 PK 인덱스와 회원_이메일_UK 인덱스 두 개가 되었다. 인조식별자를 쓰면 이처럼 인덱스가 하나 더 필요해진다.
  • GENERATED ALWAYS이면 회원번호에 값을 직접 넣을 수 없다(ORA-32795). 직접 넣는 것을 허용하려면 GENERATED BY DEFAULT를 쓴다.

12c 이전 오라클에서는 시퀀스를 만들고 INSERT 때 NEXTVAL을 쓴다. 이 방식도 중복 데이터를 막지 못하는 것은 같다.

CREATE SEQUENCE 회원_SEQ START WITH 1 INCREMENT BY 1;
CREATE TABLE 회원2 (회원번호 NUMBER PRIMARY KEY, 이메일 VARCHAR2(50) NOT NULL);
INSERT INTO 회원2 VALUES (회원_SEQ.NEXTVAL, '[email protected]');
INSERT INTO 회원2 VALUES (회원_SEQ.NEXTVAL, '[email protected]');
SELECT * FROM 회원2 ORDER BY 1;
회원번호 이메일
1 [email protected]
2 [email protected]
자동 번호 오라클 SQL Server
칼럼 속성 GENERATED [ALWAYS / BY DEFAULT] AS IDENTITY (12c 이상) IDENTITY(시작값, 증가값)
별도 객체 CREATE SEQUENCE + 시퀀스.NEXTVAL CREATE SEQUENCE + NEXT VALUE FOR 시퀀스 (2012 이상)
  • 주식별자의 네 가지 특징(유일성·최소성·불변성·존재성)과, 각 특징에 어긋나는 예를 고르는 문제
  • 식별자 분류 기준(대표성, 생성 여부, 속성 수, 대체 여부)과 각 분류의 짝(주/보조, 내부/외부, 단일/복합, 본질/인조)
  • 식별 관계는 부모 PK가 자식 PK에 포함되고, 비식별 관계는 자식의 일반 속성(FK)으로 들어간다. 비식별 관계를 선택하는 상황을 묻는 문제가 자주 나온다.
  • 인조식별자의 단점: 중복 데이터 발생 가능성(본질 속성에 UNIQUE 필요), 불필요한 인덱스 추가
  • 명칭·내역 속성은 주식별자로 쓰지 않는다.