데이터베이스 설계시 데이터 중복을 최소화하고 이상현상을 방지하여 무결성을 보장하기 위해 데이터를 구조화(분해)하는 작업
데이터의 중복을 제거, 최소화하고 이상현상을 방지해서 참고비용을 줄이고 무결성을 보장하기 위해서
회원가입 |
---|
아이디 |
이름 |
주소 |
취미 |
회원가입 테이블이 있다면 '취미' 도메인에는 (독서, 운동, 게임, 음주, 음악감상) 등의 값이 들어갈 수 있을 것이다. 만약 이를 복수 선택한다면 취미 컬럼에는 복수의 값이 들어갈 것이다.
회원가입 |
---|
아이디 |
이름 |
주소 |
취미 |
이렇게 된다면 SQL 처리가 쉽지않을것이다.
이처럼 이상 현상을 방지하기 위한 과정(process)을 정규화라고 한다.
도메인이 원자값이어야한다.
성별로 치면, '성별'이라는 컬럼에는 '남' 혹은 '여'의 값만이 들어감을 한정짓는 것이다. 이를 표현할 수 있는 범위가 도메인이고, 이 값이 원자값이어야한다는것이다. 다른말로 컬럼에 복수의 속성값이 들어가면 안된다는 뜻이다.
이러한 주문서가 한장 있다면, 주문서 테이블은
주문서 테이블
주문번호 |
---|
상품아이디 |
상품명 |
수량 |
이 될것이고 여기에 데이터를 삽입하면
주문번호 1 |
---|
상품아이디 11, 12, 13 |
상품명 불닭볶음면, 참이슬, 고향만두 |
수량 3, 2, 4 |
이처럼 테이블에 여러 컬럼에 다수의 값이 들어가게된다.
이는 1정규형을 위배한것이다. 즉 도메인이 원자값이지 않은 상태를 분리해야한다.
분리 대상은 상품아이디, 상품명, 수량이 될것이다.
이 주문서를 분해해야한다.
1 정규형의 형태의 결과는 위의 예시처럼 여러 값이 들어갈만한 컬럼을 나눠보면된다.
주문서와 주문상세 테이블로 분해할 수 있다.
아무 정규화가 이루어지지않은 주문서EX 테이블을 오른편의 두개의 테이블로 분해할 수 있다.
두 테이블의 관계를 보자.
주문상세 테이블은 주문서 테이블이 존재해야 주문 상세 테이블이 존재하기때문에 주문서 테이블은 부모테이블, 주문 상세 테이블은 자식 테이블로 관계를 맺을 수 있다.
상품번호가 11인 불닭볶음면 3봉지 이 하나의 주문(상세)에서는 주문서가 반드시 하나 존재해야한다.
주문서의 입장에서는 반드시 하나 이상 존재해야한다.
주문 상세 테이블과 주문서는 식별 관계이다.
식별관계와 비식별관계
부모테이블에서의 컬럼이 자식테이블에게 primary key로 들어오면 식별관계이고, 일반 컬럼 자리로 들어오면 비식별관계가된다.
주문 상세 테이블에서는 상품번호와 주문번호가 복합키로 기본키를 이룬다.
복합키에 대한 내용은 2정규화에서 다뤄보자.
상품번호로만 기본키가 될 수 없는 이유
다수의 사용자에게 불닭볶음면이라는 동일한 상품이 팔릴 수 있다.
주문번호로만 기본키가 될 수 없는 이유
하나의 주문서 내에서는 주문 상품이 여러개 팔릴 수 있기때문이다.
상품 번호와 주문번호를 조합해서 만든 키가 유일 값이 될 수 밖에없다.
부분 함수 종속성을 분리하여 완전 함수 종속 상태로 만든다.
1 정규화(1NF)후 주문 상세 테이블의 기본키 즉 Primary key는 복합키(composite key)로 구성된다.
복합키(composite key)란?
두 개 이상의 컬럼을 이용해 Primary key를 만드는 것 참고) 하나의 테이블에는 하나의 primary key만 존재할 수 있다. primary key는 여러개의 컬럼으로 구성될 수 있다.
복합키 (주문번호 + 상품번호)로 구성되면 두 컬럼을 조합한 값이 유일해야한다.
주문서의 주문 번호 1 불닭볶음면 상품 번호 77
주문서의 주문 번호 1 테라 상품 번호 999
라고 가정하자.
주문번호 상품번호 수량 1 77 3
주문번호 상품번호 수량 1 999 2 이러한 2개의 정보를 넣는다면 삽입이 가능하다. 주문번호와 상품번호의 조합이 유일해 이 복합키로 수량을 알 수 있기때문이다.
주문번호 상품번호 수량 1 77 2
이 정보는 정보삽입이 불가하다. 이미 유일한 키가 있기때문이다. 이때에는 UPDATE가 되어야한다.
CREATE TABLE order_detail(
order_id number ,
product_id number,
order_count number not null,
constraint my_order_detail primary key(order_id, product_id)
)
insert into order_detail(order_id,product_id,order_count) values(1,77,4);
insert into order_detail(order_id,product_id,order_count) values(1,99,2);
-- order_id 와 product_id 복합키 제약조건에 위배 error
insert into order_detail(order_id,product_id,order_count) values(1,77,2);
-- success : 주문번호가 다르므로 insert ok
insert into order_detail(order_id,product_id,order_count) values(2,77,2);
주문 상세 테이블의 기본키는 주문 번호와 상품아이디의 복합키로 구성되어있다.
이때 상품명, 상품 설명, 단가 속성은 주문 번호를 알 필요 없이 상품 번호만 알면 되기에 상품 번호에만 부분 종속성을 갖는다. 분리해서 별도의 테이블로 구성한다.
주문번호와 상품 아이디 복합키에 완전 종속되는 주문 수량 속성만 저장하도록 설계한다.
함수 종속성
A(결정자)에 의해 B(종속자)가 결정되어지는 관계예) 사원번호 1의 사원명은 아이유이다. 회원아이디 javaking의 회원명은 제임스 고슬링이다. 회원아이디 javaking의 주소는 미국이다.
완전 함수 종속
기본키를 구성하는 모든 속성에 종속되는 경우ex) 주문번호 1 과 상품번호 77이 조합된 복합키가 기본키이면 완전 함수 종속성을 가지기 위해서는 primary key 즉 기본키를 구성하는 두 속성 (주문번호 + 상품번호)에 완전 종속되는 주문 수량 속성만 두고 다른 부분 함수 종속되는 속성은 별도의 테이블로 분리해야한다.
부분 함수 종속
기본키를 구성하는 속성의 일부에 종속되는 경우ex)주문번호 + 상품번호 복합키의 일부인 상품 번호에만 종속되는 -> 부분 종속으로 상품명, 상품설명, 단가는 별도의 상품 테이블로 분리되어야한다.
주문상세 테이블과 상품 테이블을 놓고 봤을때 만약 쇼핑몰 페이지에 들어가서 상품을 선택해서 주문을 누르면 주문서 페이지로 넘어가기때문에 어떤 상품들이 있는지 보고 거기서 해당 상품을 골라야 주문을 할 수 있다.
그러니 주문 상세 테이블이 자식, 상품 테이블이 부모 테이블이다.
이 때 상품 입장에서 하나의 주문이 들어올수도, 0개 혹은 다수의 주문 상세 페이지가 만들어지는게 가능해서 0 | > 로 표현하고, 주문 상세 입장에서는 상품 한가지만 가능해서 | 로 표현한다.
이행 함수 종속성을 분리한다.
이행 함수 종속
A -> B 이고 B -> C이면 A -> C이다.
주문서 1의 담당부서 번호는 10이다. 담당부서번호 10의 부서명은 영업부이다. 주문서 1의 담당 부서명은 영업부이다. 주문서 1은 담당부서번호만 가지고 있으면 된다.
2정규화가 이루어진 상태이다.
3정규화는 일반 속성에 종속적인 속성을 분리한다.
주문서 테이블의 주문은 담당부서번호만 가지고있으면 부서명, 부서전화, 부서지역, 관리자명을 가지고 있을 필요없이 별도의 부서 테이블에서 부서번호로 참조하면된다.
주문번호를 알면 부서 번호를 알 수 있고, 부서번호를 알면 나머지 부서명, 부서전화, 관리자명을 알 수 있다. 이런 이행함수 되어지는 속성들을 분리한다.
여러 부서들이 있을거고, 그 중에 해당 주문을 담당하는 부서가 있다.
부서가 있어야 주문서에서 부서를 참조할 수 있기때문에 부서테이블이 부모, 주문서 테이블이 자식테이블이다.
주문서 입장에서는 부서가 하나 존재하기때문에 |
부서 입장에서는 여러 부서에 하나의 주문서 혹은 주문서가 존재하지않을수도있고 다수의 주문서가 존재할 수 있기때문에 0 | >의 관계를 갖는다.