기본 키
기본 키는 테이블에서 행 하나를 콕 집어 가리키는 값입니다. 테이블을 만들 때 어느 열을 그 역할로 쓸지 미리 정해 둡니다. 같은 값이 두 행에 있으면 안 됩니다. 비어 있어도 안 됩니다.
상세
주민등록번호를 떠올리면 됩니다. 이름과 생년월일이 같은 사람이 둘이어도 주민등록번호는 한 사람만 가리킵니다.
기본 키는 한 테이블에서 행 하나를 유일하게 식별하려고 고른 열, 또는 열 묶음입니다. 열 하나일 수도 있습니다. 여러 열을 묶은 것일 수도 있습니다. 여러 열을 묶은 것을 복합 키라고 부릅니다.
"고른다" 는 말이 붙는 데는 이유가 있습니다. 한 테이블에 행을 유일하게 식별할 수 있는 열이 여럿일 수 있습니다. 그런 후보를 후보 키라고 부릅니다. 그중 하나를 골라 기본 키로 지정합니다. 나머지는 후보로 남습니다.
기본 키가 되려면 두 가지를 만족해야 합니다. 값이 행마다 서로 달라야 합니다. 그리고 비어 있으면 안 됩니다. 비어 있는 값은 무엇을 가리키는지 정하지 못하기 때문입니다.
테이블 하나에 기본 키는 최대 하나입니다. 유일하게 식별할 수 있는 열이 여럿 있어도, 그중 기본 키로 지정되는 것은 하나뿐입니다.
배경
같은 값이 여러 행에 들어갈 수 있는 테이블을 생각해 봅니다. 이름 열에 "김철수" 가 세 번 들어 있다면, 그중 하나의 주소를 바꾸라는 말이 어느 행을 뜻하는지 정할 수 없습니다. 지우는 것도 마찬가지입니다. 다른 테이블에서 이 행을 가리키려 해도 가리킬 말이 없습니다.
그래서 행마다 서로 다른 값을 갖는 자리를 하나 정해 두기로 합니다. 그 자리의 값이 곧 그 행의 이름이 됩니다. 수정도 삭제도 참조도 전부 이 값을 거칩니다. 이 약속이 없으면 관계형 모델에서 테이블끼리 서로를 가리키는 일 자체가 성립하지 않습니다.
예시
PostgreSQL
열 하나를 기본 키로 지정합니다.
CREATE TABLE products (
product_no integer PRIMARY KEY,
name text,
price numeric
);
product_no 열이 이 테이블에서 행을 가리키는 값입니다. PostgreSQL 공식 문서는 이 정의가
product_no integer UNIQUE NOT NULL 로 쓴 정의와 같은 데이터를 받는다고 적습니다.
여러 열을 묶는 것도 됩니다.
CREATE TABLE example (
a integer,
b integer,
c integer,
PRIMARY KEY (a, c)
);
a 와 c 두 열의 값을 묶은 것이 행을 가리킵니다. 문법은 유니크 제약을 여러 열에 거는 것과 비슷합니다.
SQLite
SQLite 공식 문서는 WITHOUT ROWID 테이블을 뺀 모든 테이블의 행이 그 테이블 안에서 행을 유일하게 식별하는 64비트 부호 있는 정수 키를 갖는다고 적습니다. 이 정수를 보통 rowid 라고 부릅니다.
여기에 하나가 겹칩니다. rowid 테이블의 기본 키가 열 하나로 이뤄져 있고 그 열의 선언 타입이 대소문자 섞임을 가리지 않고 "INTEGER" 이면, 그 열은 rowid 의 다른 이름이 됩니다. 이런 열을 integer primary key 라고 부릅니다. 예외 한 가지가 같은 문서에 따로 적혀 있습니다.
MongoDB
관계형 데이터베이스 밖에도 같은 자리가 있습니다. MongoDB 공식 문서는 표준 컬렉션에 저장되는
문서마다 유일한 _id 필드가 필요하고 그것이 기본 키 노릇을 한다고 적습니다. 넣는 문서에
_id 가 빠져 있으면 드라이버가 ObjectId 를 만들어 채웁니다.
MongoDB 는 컬렉션을 만들 때 _id 필드에 유니크 인덱스를 기본으로 만듭니다. _id 는 문서에서
언제나 첫 번째 필드입니다. 서버가 _id 를 앞에 두지 않은 문서를 받으면 그 필드를 맨 앞으로
옮깁니다.
경계
기본 키는 유니크 제약과 자주 헷갈립니다. 둘 다 값이 겹치지 않게 막습니다. 갈리는 자리는 두 곳입니다.
첫째는 빈 값입니다. PostgreSQL 공식 문서는 유니크 제약을 비교할 때 두 NULL 값을 기본적으로 같다고 보지 않는다고 적습니다. 그래서 유니크 제약이 걸려 있어도, 제약에 들어간 열 가운데 적어도 하나가 NULL 인 행은 여러 개 저장될 수 있습니다. 기본 키는 값이 유일할 것과 NULL 이 아닐 것을 함께 요구합니다.
둘째는 개수입니다. 유니크 제약은 한 테이블에 몇 개든 걸 수 있습니다. 기본 키는 최대 하나입니다. 같은 문서는 유니크 제약을 not-null 제약과 합치면 기능적으로 거의 같은 것이 되지만 그중 하나만 기본 키로 지정될 수 있다고 적습니다.
인덱스와도 다릅니다. 기본 키는 제약이고 인덱스는 그 제약을 떠받치는 구조입니다. PostgreSQL 공식 문서는 기본 키를 붙이면 그 열이나 열 묶음에 유니크 B-tree 인덱스가 자동으로 만들어지고 그 열들이 NOT NULL 로 표시된다고 적습니다.
외래 키와는 방향이 다릅니다. 외래 키는 가리키는 쪽이고 기본 키는 가리켜지는 쪽입니다. PostgreSQL 공식 문서의 예제에서 주문 테이블의 product_no 열은 상품 테이블의 product_no 를 참조하고, 참조하는 쪽을 referencing table, 참조되는 쪽을 referenced table 이라고 부릅니다.
flowchart TD
A["orders 의 product_no 열 · 외래 키"] -->|가리킨다| B["products 의 product_no 열 · 기본 키"]
NULL 을 허용하는 PRIMARY KEY 열
NULL 이 들어간 PRIMARY KEY 열도 기본 키인가. 아닙니다. 그 엔진이 PRIMARY KEY 라고 부르는 자리이긴 하지만, 기본 키가 요구하는 것을 다 만족시키지는 않습니다.
SQLite 공식 문서가 이 경우를 스스로 밝혀 둡니다. SQL(Structured Query Language, 구조화 질의 언어) 표준에 따르면 PRIMARY KEY 는 언제나 NOT NULL 을 함의해야 하는데, 초기 판의 버그 때문에 SQLite 에서는 그렇지 않다고 적혀 있습니다. 열이 INTEGER PRIMARY KEY 이거나, 테이블이 WITHOUT ROWID 나 STRICT 이거나, 열이 NOT NULL 로 선언된 경우가 아니면, SQLite 는 대부분의 PRIMARY KEY 열에 NULL 값을 허용합니다. 같은 문서는 표준에 맞게 고칠 수도 있지만 그러면 오래된 애플리케이션이 깨질 수 있어, 고치는 대신 이 사실을 문서에 적어 두기로 했다고 밝힙니다.
판정의 근거는 요건 쪽에 있습니다. 기본 키의 요건은 유일성과 비어 있지 않음입니다. 이 요건은 어느 엔진이 그것을 어디까지 강제하느냐와 별개로 정해집니다.
관련 항목
기본 키가 놓이는 저장소
데이터베이스 · 관계형 데이터베이스 · 테이블 · 컬렉션
기본 키를 정의하거나 구현하는 표준과 제품
SQL · PostgreSQL · MySQL · SQLite · MongoDB
기본 키로 삼는 값의 갈래
자연 키 · 대리 키 · 복합 키 · UUID(Universally Unique Identifier, 범용 고유 식별자)
기본 키를 정의하는 제약과 값
유니크 제약 · NOT NULL · NULL · 인덱스 · B-tree
헷갈리는 이웃
기본 키가 쓰이는 상위 작업
다른 이름: primary key · PK