관계형 DB의 릴레이션들이 언제나 지켜야 하는 조건. 데이터가 일관된 형태를 유지하도록, 무결성을 보장하려고 둔다.

마지막 관문

같은 검사를 애플리케이션 코드에서 해도 되지 않느냐는 물음이 먼저 온다. 그런데 데이터가 들어오는 경로는 하나가 아니다. 경로가 늘 때마다 검사도 같이 늘려야 하고, 한 군데를 빠뜨리면 그쪽으로 이상한 값이 새어 들어온다. DB에 걸어두면 어느 경로로 들어오든 마지막 관문에서 걸린다.

DDL 선언과 참조 동작

스키마 기반 제약조건은 DDL로 테이블을 만들 때 함께 선언하고, 이미 만든 테이블에는 ALTER TABLE로 붙인다.

외래키는 참조하던 값이 지워지거나 바뀔 때 무엇을 할지도 같이 정한다. MySQL에서 실제로 쓸 수 있는 것은 CASCADE, SET NULL, RESTRICT다. NO ACTION은 MySQL에서 RESTRICT와 똑같이 동작하고 SET DEFAULT는 제대로 지원하지 않는다. PostgreSQL은 다섯 가지를 전부 지원한다.

이름 붙이기

CONSTRAINT 키워드로 제약조건에 이름을 붙일 수 있다. 안 붙이면 DBMS가 test_chk_1 같은 이름을 알아서 짓는데, 위반 오류가 났을 때 그 이름만 보고는 어느 조건인지 알 수 없다. MySQL이라면 SHOW CREATE TABLE 테이블명으로 되짚어야 한다. 지울 때도 고칠 때도 이름이 필요하니 처음부터 붙여두는 편이 낫다.

묵시적 제약부터 참조 무결성까지

묵시적 제약조건은 관계형 모델 자체가 갖는 제약이라 따로 선언하지 않아도 성립한다. 릴레이션은 중복 튜플을 가질 수 없고, 한 릴레이션 안에 같은 이름의 속성을 둘 수 없다.

스키마 기반 제약조건은 DDL로 스키마에 직접 명시하는 것들이라 명시적 제약조건이라고도 부른다.

도메인 제약조건은 속성값을 그 속성의 도메인 안에 묶어둔다. 학년에 100이 들어갈 수 없다.

키 제약조건 아래에서는 서로 다른 튜플이 같은 키 값을 가질 수 없다. 에서 이어 본다.

NULL 값 제약조건을 걸면, 그러니까 NOT NULL로 선언하면 그 속성은 NULL을 가질 수 없다. UNIQUE는 MySQL과 PostgreSQL에서 NULL의 중복을 허용하므로, NULL을 받을 이유가 없는 속성이면 UNIQUENOT NULL을 함께 건다.

개체 무결성 제약조건은 기본키에 NULL을 허용하지 않는다. 식별하라고 둔 것이 식별할 수 없는 값이면 모순이기 때문이다.

참조 무결성 제약조건 아래에서 외래키는 참조하는 릴레이션에 실제로 있는 값이거나 NULL이어야 한다. 없는 팀을 가리키는 선수가 생기지 않게 막는다.

트랜잭션 일관성이 미치는 범위

트랜잭션의 일관성이 보장하는 범위가 정확히 여기 선언된 것들까지다. “잔고는 음수가 될 수 없다”를 CHECK 제약조건으로 걸어두면 DBMS가 막아주지만, 걸어두지 않았다면 애플리케이션이 챙길 몫으로 남는다. 트랜잭션이 원자성과 격리를 아무리 지켜도, 무엇이 올바른 값인지 알려주지 않으면 잘못된 값을 막을 방법이 없다.

관련

출처