1. 키
1-1. 중복을 허용하지 않는 키
릴레이션은 중복된 튜플을 허용하지 않는다. 즉, 두개의 레코드가 있다면 무조건 하나 이상의 튜플이 달라야 한다.
이를 위해, 키로 중복된 튜플을 허용하지 않는다는 제약 조건을 만족시킨다.
1-2. 슈퍼 키
튜플을 유일하게 식별할 수 있는 하나의 속성(단일) 혹은 속성의 집합(복합)
=> 사실상 단일 속성으로 겹치지 않는 튜플은 거의 없다고 생각한다.
1-3. 후보 키
튜플을 유일하게 식별할 수 있는 속성의 최소 집합.
=> 단일이나, 복합의 집합에서 그 어떤 원소도 중복되지 않고 식별자로 활용할 수 있는 키를 뜻한다.
1-4. 기본 키(PK)
=> 후보 키 중 하나를 선택한다.
1-5. 외래 키(FK)
다른 릴레이션에서 다른 릴레이션의 기본 키를 참조하는 경우
1-6. 가상키(대체키)
기본 키가 마땅히 없거나 너무 길 떄, 임의로 만들어 사용한다.
=> MySQL에서는 Auto-Increment를 사용한다.
2. 기본 키 제약 조건(기본 키를 선택할 때, 데이터베이스가 무결성을 위해 임의로 적용하는 제약조건)
2-1. 중복이 없어야 한다.(UNIQUE)
2-2. NULL값은 허용하지 않는다.(@NotNull, @NotlBlank 등등)
2-3. 변하지 않는다.(update 시 에러)
3. 외래 키 제약 조건(외래키를 뒀을 때, 데이터베이스가 무결성을 위해 임의로 적용하는 제약 조건)
3-1. 다른 릴레이션의 기본키를 참조
3-2. PK가 변경(사실상 변경될 일은 없다.)되면, FK 또한 변경되어야 한다.
3-3. NULL 값과 중복값 등이 허용된다.
3-4. 외래 키는 기본키가 될 수 있다.
3-5. PK 삭제 시 FK를 가진 튜플이 어떻게 될 지 cascade로 고려해 보아야 한다.(JPA에서는 cascade를 신경쓰지 말자 오히려 영속성 컨텍스트에서 정합성 문제가 발생할 수 있다.)
=> 부모 튜플이 삭제되었을 때, 자식 튜플의 FK를 NULL로 할지 아니면, 아예 삭제해버릴 지
@ManyToOne(cascade = CascadeType.REMOVE)
위의 예제는 JPA의 cascade다.
JPA의 cascade는 ORM 상에서 관리하는 것이기에 ON DELETE CASCADE 와 다르다.
기억하도록 하자.
보통 cascade는 DB 단에서가 아닌 ORM 단에서 관리해준다고 한다.
==> 제약 조건은 JPA의 영속성 컨텍스트로 인해, 많이 다르다.
==> 따로 JPA를 공부해보자.
4. pk가 필요한 이유
4-1. 테이블에 중복 튜플을 허용하지 않는다.(하나라도 달라야 한다.)
4-2. 클러스터링 인덱스를 통한 조회 성능 증가(기본 키를 최대한 짧게 해야한다.)
4-3. FK 참조 지원
5. 안티패턴들
5-1. 각 행을 유일하게 식별할 수 있게 하는 키가 있음에도, PK를 AUTO_INCREMENT로 생성한다.
=> 이는 쓸모없는 키가 될 수 있다.
5-2. 다 대 다 연관관계에서 2개의 FK 묶음이 중복을 허용하지 않는 경우, PK를 의미없이 둔 경우
=> FK 2개를 중복 PK로 하면된다.
5-3. a 테이블의 키 이름이 id인 경우
=> 이름이 모호해서 a 테이블의 id인지 b 테이블의 id인지 알 수 없다.
3번을 제외한 2개의 테이블은 복합 키를 사용하지 않아 생긴 것이다.
복합 키를 사용하면 이를 참조하고 있는 FK도 복합 FK가 될 수 있다.
6. PK를 정하는 방법
PK는 제약조건이다.
즉, 데이터 타입이 아니다.
어떤 특정 칼럼에도 PK를 잡을 수 있으며, Auto_Increment 값에도 PK를 쓸 수 있다.
6-1. 내가 정한 규칙
6-1-1. 테이블에는 무조건 PK를 넣는다.(중복 방지, 클러스터링 인덱스를 통한 조회 성능 증가, FK 참조 지원)
6-1-2. 다대다 연결에서는 2개의 FK를 UNIQUE 조건을 넣던가, 복합 PK로 만든다.
6-1-3. Auto_Increment가 아닌, 다른 컬럼(자연키)으로 PK를 넣는것을 고려해본다.
6-1-4. 3번 이후 만약, 다른 컬럼의 사이즈가 크다면, 가상키를 고려해본다.
6-1-5. 어떤 키로 위의 조건들을 만족하고, 가장 식별자를 잘 나타낼 수 있다면,