현재 선택한 정보처리 과정

정보처리기사 필기 이론 학습

이론 목록으로 돌아가기

키와 무결성 제약조건

슈퍼키는 유일성, 후보키는 유일성과 최소성을 만족하며 기본키는 선택된 후보키다. 외래키는 참조 역할을 하는 속성으로 자식 값의 유일성을 자동 요구하지 않는다. 도메인·개체·참조·사용자 정의 무결성을 SQL 제약조건과 연결해 이해해야 한다. UNIQUE·CHECK·DEFAULT는 NULL 처리와 보장 범위가 서로 다르다.

예상 읽기 16

키가 필요한 이유

관계형 데이터베이스의 한 행은 하나의 개체나 업무 사실을 나타낸다. 여러 행 가운데 특정 행을 정확히 찾고, 다른 테이블의 행과 안전하게 연결하려면 식별 기준이 필요하다. 이 역할을 하는 속성 또는 속성 집합이 키(Key)다.

키는 현재 저장된 표본 데이터가 우연히 중복되지 않는다는 사실만으로 결정하지 않는다. 앞으로 허용할 모든 데이터 상태에서도 업무 규칙상 값을 유일하게 식별할 수 있어야 한다. 예를 들어 지금 직원 이름이 모두 다르더라도 동명이인이 입사할 수 있다면 이름은 직원의 키가 아니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
현재 데이터에서 값이 우연히 다름 ≠ 키
업무 규칙상 모든 정상 상태에서 유일함 = 키 후보가 될 수 있음

키 문제에서는 다음 세 질문을 순서대로 확인한다.

  1. 이 속성 집합으로 각 행을 유일하게 식별할 수 있는가?
  2. 일부 속성을 빼도 유일하다면 불필요한 속성이 포함된 것은 아닌가?
  3. 식별용 키인지, 다른 행을 참조하는 외래키인지 역할이 무엇인가?

키의 종류와 포함 관계

슈퍼키와 후보키

슈퍼키(Superkey)는 릴레이션의 각 튜플을 유일하게 식별할 수 있는 속성 집합이다. 유일성만 만족하면 되므로 식별에 필요하지 않은 속성이 함께 들어 있어도 슈퍼키가 될 수 있다.

후보키(Candidate Key)는 슈퍼키 중에서 최소성을 만족하는 키다. 여기서 최소성은 구성 속성 가운데 어느 하나라도 제거하면 더 이상 유일하게 식별할 수 없다는 뜻이다.

구분유일성최소성핵심 의미
슈퍼키만족반드시 만족할 필요 없음행을 유일하게 식별하는 모든 속성 집합
후보키만족만족불필요한 속성이 없는 최소 슈퍼키

다음 릴레이션을 보자.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
MEMBER(member_id, email, name)
업무 규칙: member_id와 email은 각각 회원을 유일하게 식별한다.

후보키는 {member_id}, {email}이다. 다음 집합들은 모두 슈퍼키지만 후보키는 아니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
{member_id, name}
{email, name}
{member_id, email}
{member_id, email, name}

각 집합에서 name이나 다른 식별자를 제거해도 유일성이 남기 때문이다.

후보키의 최소성은 “모든 후보키 가운데 열 수가 가장 적다”는 뜻이 아니다. 각 후보키 자신의 진부분집합이 키가 아니면 된다. 따라서 한 릴레이션에 한 열짜리 후보키와 두 열짜리 후보키가 동시에 존재할 수 있다.

예를 들어 다음 업무 규칙에서는 {student_id}{school_code, admission_no}가 모두 후보키가 될 수 있다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
STUDENT(student_id, school_code, admission_no, name)

- student_id는 전체 학생을 유일하게 식별한다.
- 같은 학교 안에서 admission_no는 중복되지 않는다.

{school_code, admission_no}에서 어느 한 열만 제거하면 전체 학생을 식별할 수 없으므로 두 열짜리 후보키도 최소성을 만족한다.

기본키와 대체키

후보키가 여러 개라면 그중 하나를 대표 식별자로 선택한다. 선택된 후보키가 기본키(Primary Key)이고, 선택되지 않은 나머지 후보키가 대체키(Alternate Key)다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
슈퍼키
└─ 후보키: 유일성 + 최소성
   ├─ 기본키: 후보키 중 대표로 선택된 하나
   └─ 대체키: 선택되지 않은 나머지 후보키

한 릴레이션에는 후보키가 여러 개 존재할 수 있지만 기본키는 하나만 선택한다. 기본키 하나가 여러 속성으로 구성되는 복합 기본키일 수 있으므로 “기본키는 반드시 한 열이다”라는 설명은 옳지 않다.

앞의 회원 예에서 member_id를 기본키로 선택하면 email은 대체키다. 대체키의 유일성도 계속 보존해야 하므로 SQL에서는 보통 UNIQUE와 필요한 NOT NULL을 함께 사용한다.

단순키와 복합키

구분의미
단순키(Simple Key)한 속성으로 구성된 키{member_id}
복합키(Composite Key)둘 이상의 속성으로 구성된 키{school_code, admission_no}

복합키의 유일성은 각 열 하나하나가 아니라 열 조합 전체에 적용된다. 예를 들어 (employee_id, project_id)가 복합 기본키라면 같은 직원이 서로 다른 프로젝트에 참여하는 것은 허용되고, 서로 다른 직원이 같은 프로젝트에 참여하는 것도 허용된다. 금지되는 것은 두 값의 동일한 조합이 다시 나타나는 경우다.

외래키

외래키(Foreign Key)는 한 릴레이션의 속성 또는 속성 집합이 다른 릴레이션이나 같은 릴레이션의 식별 가능한 키를 참조하도록 하는 키다. SQL에서는 일반적으로 참조 대상이 PRIMARY KEY, UNIQUE 제약 등으로 유일성이 보장되어 있어야 한다.

외래키는 슈퍼키·후보키·기본키의 포함관계에서 자동으로 파생되는 종류가 아니라 참조 역할에 따른 분류다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
식별 역할: 슈퍼키 → 후보키 → 기본키·대체키
참조 역할: 외래키

따라서 한 속성이 두 역할을 동시에 가질 수도 있다. 예를 들어 연결 테이블의 employee_id는 부모 테이블을 참조하는 외래키이면서 복합 기본키의 일부일 수 있다.

외래키에 관한 핵심 성질은 다음과 같다.

  • 다른 테이블뿐 아니라 같은 테이블을 참조할 수 있다.
  • 부모의 기본키뿐 아니라 유일성이 보장된 대체키를 참조할 수 있다.
  • 자식 테이블에서 같은 외래키 값이 여러 번 나타나는 것은 일반적으로 허용된다.
  • 관계가 선택적이면 외래키에 NULL을 허용할 수 있다.
  • 복합키를 참조하면 외래키도 대응하는 열 수와 순서를 갖는 복합 외래키가 된다.
  • 외래키 열이 자동으로 인덱스가 된다고 단정할 수 없다. 제약과 인덱스는 역할이 다르며 자동 생성 여부는 DBMS에 따라 다르다.
좌우로 이동해 그림을 확인하세요.그림 크게 보기
키의 포함 관계와 외래키 참조
키의 포함 관계와 외래키 참조

키의 포함 관계와 외래키 참조

슈퍼키는 유일성, 후보키는 유일성과 최소성을 갖는다. 선택한 후보키가 기본키이고 나머지는 대체키다. 최소성은 어떤 열도 빼면 안 된다는 뜻이다. 외래키는 별도의 참조 역할로, 허용된 NULL 또는 존재하는 참조 키를 갖고 자기 참조도 가능하다.

자연키와 대리키

키는 값의 출처에 따라 자연키와 대리키로도 구분한다.

구분자연키(Natural Key)대리키(Surrogate Key)
값의 의미업무 자체에서 의미가 있음식별을 위해 시스템이 인위적으로 부여
사원번호, 국가코드+면허번호순번 ID, UUID
장점업무 의미를 직접 반영짧고 안정적인 식별자를 만들기 쉬움
주의점업무 정책에 따라 변경되거나 길 수 있음자연 식별 규칙의 중복을 스스로 막지 못함

대리키를 기본키로 사용했다고 해서 업무상 중복 허용 여부가 사라지는 것은 아니다. 다음 테이블에서 member_id가 서로 다르면 같은 이메일을 여러 번 넣을 수 있으므로, 이메일이 업무상 유일해야 한다면 별도 UNIQUE가 필요하다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
CREATE TABLE member (
    member_id INTEGER PRIMARY KEY,
    email     VARCHAR(255) NOT NULL UNIQUE,
    name      VARCHAR(100) NOT NULL
);

기본키를 선택할 때에는 보통 다음 조건을 함께 고려한다.

  • 모든 정상 상태에서 유일한가?
  • 최소성을 만족하는 후보키인가?
  • NULL이 될 수 없는가?
  • 값이 자주 바뀌지 않는가?
  • 지나치게 길거나 많은 열로 구성되지 않았는가?
  • 개인정보나 외부 정책 변경에 과도하게 의존하지 않는가?

유일성과 최소성은 후보키의 논리적 조건이다. 짧음, 안정성, 사용 편의성은 여러 후보키 가운데 기본키를 고를 때의 설계 기준이다.

키와 인덱스는 같은 개념이 아니다

키와 무결성 제약조건은 데이터가 지켜야 할 논리적 규칙이고, 인덱스는 데이터를 빠르게 찾기 위한 물리적 접근 구조다.

구분키·제약조건인덱스
목적유일성·참조·허용 범위 등 데이터 규칙 보장검색·정렬·조인의 접근 성능 향상
관점논리적 설계물리적 설계
위반 시잘못된 데이터 입력을 거부일반적으로 데이터 유효성 자체를 정의하지 않음
관계DBMS가 제약 구현을 위해 인덱스를 사용할 수 있음인덱스가 있다고 자동으로 후보키가 되는 것은 아님

PRIMARY KEYUNIQUE를 만들 때 DBMS가 고유 인덱스를 자동 생성하는 경우가 많지만, 이것은 구현 방법이다. “기본키와 인덱스는 같은 것이다” 또는 “외래키를 선언하면 항상 자식 인덱스가 자동 생성된다”는 식으로 일반화하면 안 된다.

무결성의 의미와 종류

데이터 무결성(Data Integrity)은 데이터가 정의된 구조와 업무 규칙을 만족해 정확하고 일관된 상태를 유지하는 성질이다. 제약조건은 잘못된 상태가 저장되는 것을 데이터베이스가 직접 거부하도록 선언한 규칙이다.

시험에서는 다음 분류를 자주 구분한다.

무결성 종류보호하는 대상대표 규칙주요 구현 수단
도메인 무결성한 속성에 허용되는 값급여는 0 이상, 상태는 정해진 코드 중 하나자료형, NOT NULL, CHECK
키 무결성식별 키의 중복후보키 값은 튜플을 유일하게 식별PRIMARY KEY, UNIQUE + NOT NULL
개체 무결성각 튜플의 식별 가능성기본키는 중복될 수 없고 NULL일 수 없음PRIMARY KEY
참조 무결성릴레이션 사이의 참조 일관성외래키는 존재하는 부모 키를 참조하거나 허용된 NULLFOREIGN KEY
사용자 정의·의미 무결성업무 고유 규칙퇴사일은 입사일보다 빠를 수 없음CHECK, 트리거, 트랜잭션, 제어된 애플리케이션 로직

교재에 따라 키 무결성을 개체 무결성에 포함해 설명하기도 한다. 문제에서 분류 체계를 제시하면 그 체계를 따르되, 개체 무결성의 핵심은 기본키의 유일성과 비NULL 식별이라는 점을 놓치지 않는다.

SQL 제약조건과 실제 동작

NOT NULL

NOT NULL은 해당 열에 NULL을 저장하지 못하게 한다. 값의 범위나 중복 여부까지 검사하지는 않는다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
name VARCHAR(100) NOT NULL

빈 문자열 '', 숫자 0, 공백 문자열은 일반적으로 NULL과 다른 값이다. 다만 빈 문자열 처리처럼 제품별 예외가 있을 수 있으므로 특정 DBMS를 전제로 한 문제에서는 그 제품 규칙을 따른다.

UNIQUE

UNIQUE는 지정한 열 또는 열 조합에서 중복되는 비NULL 키 값을 제한한다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
CONSTRAINT uq_member_email UNIQUE (email)

복합 UNIQUE(a, b)ab 각각을 유일하게 만드는 것이 아니라 (a, b) 조합의 중복을 막는다.

NULL을 포함한 UNIQUE의 세부 동작은 DBMS와 옵션에 따라 다를 수 있다. 여러 제품에서는 NULL을 서로 같은 값으로 보지 않아 NULL이 여러 번 허용될 수 있다. 따라서 논리 모델의 후보키를 SQL의 대체키로 구현하려면 UNIQUE만 보고 비NULL을 가정하지 말고 필요한 열에 NOT NULL을 명시한다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
email VARCHAR(255) NOT NULL UNIQUE

PRIMARY KEY

PRIMARY KEY는 선택된 후보키를 선언한다. 기본키는 유일해야 하고 NULL일 수 없다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
CREATE TABLE project (
    project_id   INTEGER,
    project_code VARCHAR(30) NOT NULL UNIQUE,
    project_name VARCHAR(100) NOT NULL,
    CONSTRAINT pk_project PRIMARY KEY (project_id)
);

한 테이블에는 기본키 제약을 하나만 둘 수 있지만, 기본키 제약 안에 여러 열을 넣을 수 있다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
PRIMARY KEY (employee_id, project_id, assigned_on)

FOREIGN KEY

외래키는 자식 행의 참조값이 부모의 유일한 키와 일치하도록 한다. 외래키가 NULL을 허용하고 실제 값이 NULL이면 “연결 대상이 없음”으로 처리할 수 있다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
FOREIGN KEY (department_code)
    REFERENCES department(department_code)

위 예에서 부모의 department_code는 기본키가 아니어도 UNIQUE로 유일성이 보장되어 있으므로 참조 대상이 될 수 있다.

외래키는 자식 값의 유일성을 요구하지 않는다. 한 부서에 여러 직원이 소속될 수 있으므로 여러 직원 행이 같은 department_code를 가져도 참조 무결성에 어긋나지 않는다.

자기 참조 외래키

외래키는 같은 테이블의 키를 참조할 수 있다. 직원의 관리자 관계가 대표적이다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
manager_id INTEGER,
FOREIGN KEY (manager_id)
    REFERENCES employee(employee_id)

최상위 관리자는 관리자가 없으므로 manager_id에 NULL을 허용할 수 있다. 자기 참조가 가능하다는 것과 자기 자신을 관리자로 지정해도 된다는 것은 다른 문제다. 직접 자기 참조를 금지하려면 별도 업무 규칙이 필요하다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
CHECK (manager_id IS NULL OR manager_id <> employee_id)

참조 동작

부모 키가 삭제·변경될 때 자식 참조를 어떻게 처리할지 정한다. 지원 구문과 검사 시점은 DBMS에 따라 다르다.

동작기본 의미
RESTRICT·NO ACTION참조 무결성 위반을 허용하지 않도록 작업 제한
CASCADE부모의 삭제·키 변경을 자식에 연쇄 반영
SET NULL자식 외래키를 NULL로 변경; NULL 허용 필요
SET DEFAULT자식 외래키를 기본값으로 변경; 기본값도 참조 규칙 충족 필요

ON DELETE CASCADE는 부모 삭제가 자식 삭제로 전파되는 방향이다. 자식을 지우면 부모도 지워진다는 뜻은 아니다. 복합 외래키는 부모 키의 열 수와 대응 순서를 맞추고, 필수 참조라면 구성 열의 NOT NULL도 확인한다.

CHECK와 3값 논리

CHECK는 조건 결과가 FALSE일 때 행을 거부한다. 조건이 TRUE이거나 NULL 때문에 UNKNOWN이면 통과할 수 있다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
salary NUMERIC CHECK (salary >= 0)

위 선언은 음수를 거부하지만 salary가 NULL인 행까지 막는다고 단정할 수 없다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
salary = 1000  → 1000 >= 0 = TRUE   → 허용
salary = -1    → -1 >= 0 = FALSE    → 거부
salary = NULL  → NULL >= 0 = UNKNOWN → 허용 가능

NULL도 금지하려면 NOT NULL을 함께 사용한다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
salary NUMERIC NOT NULL CHECK (salary >= 0)

행 하나의 여러 열을 비교하는 업무 규칙도 CHECK로 표현할 수 있다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
CHECK (retired_on IS NULL OR retired_on >= hired_on)

그러나 여러 행의 합계, 다른 테이블의 집계값, 시간에 따라 변하는 복잡한 규칙은 일반적인 행 단위 CHECK만으로 표현하기 어렵거나 DBMS에서 서브쿼리를 허용하지 않을 수 있다. 이런 규칙은 트랜잭션 격리, 트리거, 별도 검증 절차, 제어된 애플리케이션 로직 등을 함께 설계한다.

DEFAULT는 단독으로 무결성을 보장하지 않는다

DEFAULT는 값이 생략되었을 때 넣을 기본값을 제공한다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
status VARCHAR(20) DEFAULT 'READY'

이 선언만으로 status가 항상 READY라는 뜻은 아니며, 잘못된 다른 문자열 입력도 막지 못한다. 허용 상태를 제한하려면 CHECK를 함께 둔다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
status VARCHAR(20) NOT NULL DEFAULT 'READY'
    CHECK (status IN ('READY', 'RUNNING', 'DONE'))

짧은 제약조건 판별

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
CREATE TABLE member (
    member_id INTEGER PRIMARY KEY,
    email VARCHAR(100) NOT NULL UNIQUE,
    age INTEGER CHECK (age >= 0)
);

member_id는 기본키이고 email은 업무상 유일한 식별자라고 할 때 대체키로 사용할 수 있다. 같은 email을 다시 넣으면 UNIQUE 위반이다. age=-1은 CHECK 위반이지만 age=NULL은 조건이 UNKNOWN이므로 이 선언만으로 거부되지 않는다. 나이를 반드시 입력해야 한다면 NOT NULL을 추가한다.

UNIQUE(a,b)는 a나 b 각각이 아니라 두 값의 조합을 유일하게 만든다. (1,10)(1,20)은 서로 다른 조합이므로 허용할 수 있다.

참조 동작과 NULL 조합 검사

SQLite의 UNIQUE는 NULL들을 서로 다른 값처럼 취급하므로 같은 UNIQUE 열에 NULL인 행 둘이 들어갈 수 있다. 일반적인 후보키 의미까지 표현하려면 필요한 NOT NULL을 별도로 확인해야 한다. 다른 제품·옵션의 NULL 유일성 처리를 SQLite와 같다고 단정하지 않는다.

ON DELETE SET NULL을 지정했더라도 자식 열에 NOT NULL이 걸려 있으면 참조 중인 부모 삭제가 실패할 수 있다. 참조 동작이 다른 제약조건을 없애 주는 것이 아니다. SET DEFAULT 역시 기본값이 유효한 부모 키를 가리키거나 허용되는 NULL이어야 한다.

복합 값 두 열 a·b가 모두 비어 있거나 모두 채워져야 한다면 다음 조건을 사용할 수 있다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
CHECK ((a IS NULL AND b IS NULL)
    OR (a IS NOT NULL AND b IS NOT NULL))

이 식은 IS NULL을 사용하여 두 열의 NULL 조합을 판정하므로 한 열만 채워진 상태를 거부한다. NULL 여부만 검사할 뿐 참조 대상의 존재를 대신 검사하지는 않으므로 외래키는 따로 필요하다.

키의 중복·비NULL은 개체와 키 무결성, 부모 키 존재는 참조 무결성, 허용된 값의 범위는 도메인 무결성과 연결하여 읽는다. 제약조건을 통과해도 다른 사람의 유효한 키로 잘못 매핑한 업무 오류까지 자동으로 검출되는 것은 아니다.