SQL 개발자(SQLD)

SQL 개발자(SQLD) 시험 노트개념 정리17 MIN

엔터티와 속성, 그리고 NULL

SQLD 1과목의 둘째 자리입니다. 엔터티의 여섯 가지 특징과 두 갈래 분류, 기본·설계·파생 속성과 단일값·복합·다중값 속성, 도메인, 그리고 NULL이 연산과 집계 함수에서 어떻게 움직이는지를 정리합니다.

앞 노트에서 모델링의 단계와 3층 스키마를 봤습니다. 이번에는 그 모델을 이루는 두 부품 — 상자에 해당하는 엔터티와 그 안에 적히는 속성을 다룹니다. 마지막 절의 NULL은 1과목에서는 「속성이 값을 갖지 않는 상태」로 짧게 나오지만, 2과목의 연산·함수·집계·조인 전체에 걸쳐 실점을 만드는 자리라 여기서 먼저 성질을 못 박아 둡니다.

엔터티가 되는 조건

엔터티는 업무에서 관리해야 하는, 서로 구별되는 것들의 집합입니다. 「김팔딘」한 사람이 엔터티가 아니라 「고객」이라는 집합이 엔터티이고, 「김팔딘」은 그 집합의 한 인스턴스입니다. 이 집합과 인스턴스의 구별이 뒤의 모든 규칙의 출발점입니다.

여섯 가지 특징

특징 뜻 어겼을 때
업무에서 필요로 함 그 업무가 실제로 쓰는 정보다 아무도 안 보는 테이블이 생긴다
유일한 식별자로 식별 가능 인스턴스를 하나로 짚을 수 있다 같은 행이 둘인지 하나인지 모른다
인스턴스의 집합 인스턴스가 두 개 이상이다 값이 하나뿐이면 속성이지 엔터티가 아니다
업무 프로세스에 이용됨 어떤 프로세스가 이것을 쓴다 만들기만 하고 안 쓰는 자료가 남는다
반드시 속성을 가짐 식별자 말고 다른 속성이 있다 관계만 있는 껍데기가 된다
다른 엔터티와 관계를 가짐 최소 한 개의 관계를 갖는다 모델에서 떨어져 나온 섬이 된다

마지막 특징에는 예외가 있습니다. 코드성 엔터티나 통계용 엔터티처럼 다른 엔터티와 관계를 굳이 잇지 않는 것들이 있고, 이때는 관계가 없어도 모델의 결함이 아닙니다. 시험은 이 여섯 중 하나를 슬쩍 뒤집어 「인스턴스가 하나뿐이어도 엔터티가 될 수 있다」 같은 보기로 냅니다.

엔터티가 아닌 것

「고객등급」이 엔터티인지 속성인지는 그 자체로 관리할 정보가 더 있는지가 정합니다. 등급 코드와 이름 말고 할인율·적용 시작일 같은 속성이 붙고 인스턴스가 여럿이면 엔터티이고, 고객 행마다 붙는 값 하나에 지나지 않으면 고객 엔터티의 속성입니다. 「그 안에 또 무엇을 적을 것이 있는가」를 물어보는 것이 가장 빠른 판별법입니다.

엔터티의 두 갈래 분류

같은 엔터티를 두 축으로 나눕니다. 축이 둘이라는 것을 놓치면 「기본 엔터티이면서 유형 엔터티」 같은 조합을 틀린 보기로 착각합니다.

유무형에 따라

종류 뜻 예
유형 엔터티 물리적 형태가 있고 안정적이다 사원, 상품, 물류창고
개념 엔터티 형태가 없는 개념·관리 단위다 조직, 부서, 보험상품, 계좌
사건 엔터티 업무 수행에 따라 발생한다 주문, 청구, 접수, 입금

사건 엔터티는 발생량이 가장 많고 시간이 지날수록 행이 쌓입니다. 통계와 이력의 재료가 대부분 여기서 나옵니다. 유형과 개념을 가르는 기준은 손으로 만질 수 있는가가 아니라 업무에서 그것을 물리적 실체로 다루는가입니다. 「계좌」는 통장이라는 물건이 있어도 업무가 관리하는 것은 잔액과 상태라 개념 엔터티입니다.

발생 시점에 따라

종류 뜻 특징 예
기본 엔터티 다른 엔터티에서 나오지 않고 스스로 생성된다 자신의 고유한 주식별자를 갖는다 사원, 부서, 상품
중심 엔터티 기본 엔터티에서 발생한다 업무의 중심이 되고 다른 엔터티를 낳는다 주문, 계약, 청구
행위 엔터티 둘 이상의 엔터티에서 발생한다 다른 엔터티에서 받은 식별자를 갖는다 주문상세, 이력, 로그

가르는 기준은 주식별자가 어디서 왔는가입니다. 자기 것이면 기본, 하나에서 받았으면 중심, 둘 이상에서 받아 조합했으면 행위입니다. 「주문상세」가 행위 엔터티인 이유는 주문번호와 상품번호를 함께 받아 식별하기 때문입니다.

속성

속성은 엔터티가 관리하는, 더 이상 쪼갤 수 없는 데이터의 단위입니다. 엔터티가 행의 집합이라면 속성은 열이고, 한 인스턴스는 속성마다 값을 하나씩 갖습니다.

네 낱말의 관계

엔터티·인스턴스·속성·속성값은 서로 몇 대 몇으로 묶이는지가 정해져 있고, 이 조합이 그대로 문제로 나옵니다.

관계 대응 읽는 법
엔터티 : 인스턴스 1 : M 한 엔터티에 인스턴스가 여럿이다
엔터티 : 속성 1 : M 한 엔터티에 속성이 여럿이다
인스턴스 : 속성값 1 : M 한 인스턴스가 속성값을 여럿 갖는다
속성 : 속성값 1 : 1 한 인스턴스 안에서 한 속성은 값 하나다

마지막 줄만 1:1입니다. 「한 속성이 값을 여럿 가질 수 있다」는 보기가 나오면 틀린 것이고, 실제로 여럿을 갖고 싶으면 앞에서 본 다중값 속성이라 엔터티를 분리해야 합니다.

특성에 따라

종류 뜻 예
기본 속성 업무에서 그대로 가져온 원래의 속성 회원명, 주문일자, 단가
설계 속성 업무에 없던 것을 설계자가 만든 속성 회원번호, 상품분류코드
파생 속성 다른 속성에서 계산해 만든 속성 주문금액 합계, 평균 단가, 나이

파생 속성은 되도록 적게 둡니다. 원본이 바뀌면 함께 갱신해야 하는 자리라 값이 어긋나기 쉽습니다. 그래도 두는 이유는 매번 계산하는 비용이 클 때인데, 그때는 「누가 언제 갱신하는가」를 모델에 함께 적어 둡니다.

값의 개수에 따라

종류 뜻 처리
단일값 속성 값이 하나다 그대로 둔다
복합 속성 여러 의미가 한 칸에 들어 있다 우편번호·시도·시군구로 쪼갠다
다중값 속성 값이 여러 개다 별도의 엔터티로 분리한다

전화번호가 집·휴대전화·회사로 여럿이면 다중값 속성입니다. 컬럼을 전화번호1·전화번호2로 늘리는 대신 「연락처」 엔터티를 따로 만드는 것이 정석이고, 이것이 뒤에 나올 제1정규형의 내용이기도 합니다.

도메인

도메인은 그 속성이 가질 수 있는 값의 범위입니다. 데이터 타입과 길이, 그리고 제약조건까지 포함합니다. 「점수」 속성의 도메인이 「0 이상 100 이하의 정수」라면, 그 범위를 벗어난 값은 모델 차원에서 이미 잘못된 값입니다. 물리 모델에서는 이것이 NUMBER(3)과 CHECK 제약으로 내려앉습니다.

도메인을 미리 정의해 두면 같은 뜻의 속성이 테이블마다 다른 타입으로 흩어지는 일을 막을 수 있습니다. 「사업자등록번호」를 한 곳에서는 숫자로, 다른 곳에서는 열 자리 문자로 잡아 두면 조인할 때 형변환이 끼어 인덱스를 못 타게 됩니다. 이름이 같은 속성은 도메인도 같아야 한다는 것이 모델링의 기본 규약입니다.

NULL

NULL은 아직 정해지지 않았거나 알 수 없어서 값이 존재하지 않는 상태입니다. 0도 아니고 빈 문자열도 아닙니다 — 0은 「0이라는 값이 있다」이고 NULL은 「값이 없다」입니다.

연산에서의 NULL

NULL이 하나라도 끼면 산술 연산의 결과는 NULL입니다.

SELECT 1000 + NULL FROM DUAL;   -- 결과: NULL
SELECT NULL = NULL FROM DUAL;   -- 참도 거짓도 아니다

그래서 NULL은 = 로 비교할 수 없고 IS NULL·IS NOT NULL로만 판별합니다. WHERE 비고 = NULL은 문법 오류가 아니라 한 행도 안 나오는 조건이 되어 조용히 결과를 비웁니다.

집계 함수에서의 NULL

집계 함수는 반대로 움직입니다 — NULL인 행을 아예 빼고 계산합니다.

함수 NULL 처리
COUNT(*) NULL 여부와 무관하게 행을 전부 센다
COUNT(컬럼) 그 컬럼이 NULL인 행은 안 센다
SUM·AVG·MAX·MIN NULL을 뺀 값들로만 계산한다

AVG가 가장 자주 실점하는 자리입니다. 값이 10, 20, NULL인 세 행에서 AVG(점수)는 (10+20)/2=15(10+20)/2 = 15이지 (10+20+0)/3=10(10+20+0)/3 = 10이 아닙니다. NULL을 0으로 치고 싶으면 AVG(NVL(점수, 0))처럼 먼저 바꿔야 하고, 그러면 결과가 10이 됩니다. 두 값이 다르다는 사실 자체가 문제로 나옵니다.

연습 문제

  1. 엔터티의 특징으로 옳지 않은 것은?
    ① 업무에서 필요로 하는 정보여야 한다
    ② 유일한 식별자로 식별이 가능해야 한다
    ③ 인스턴스가 하나뿐이어도 엔터티가 될 수 있다
    ④ 식별자 외의 속성을 반드시 가져야 한다
    ③. 엔터티는 인스턴스의 집합이므로 두 개 이상이어야 합니다. 값이 하나뿐이면 엔터티가 아니라 다른 엔터티의 속성으로 두는 것이 맞습니다.
  2. 「주문상세」 엔터티가 발생 시점에 따른 분류에서 행위 엔터티인 이유로 옳은 것은?
    ① 물리적 형태가 없기 때문이다
    ② 업무 수행에 따라 발생하기 때문이다
    ③ 주문과 상품 둘에서 식별자를 받아 만들어지기 때문이다
    ④ 인스턴스가 가장 많이 쌓이기 때문이다
    ③. 발생 시점 분류의 기준은 주식별자가 어디서 왔는가입니다. 둘 이상에서 받으면 행위 엔터티입니다. ①은 개념 엔터티, ②는 사건 엔터티의 설명으로 유무형 분류 쪽 이야기입니다.
  3. 속성의 종류가 나머지와 다른 하나는?
    ① 회원명
    ② 주문일자
    ③ 단가
    ④ 주문금액 합계
    ④. ①②③은 업무에서 그대로 가져온 기본 속성이고, 주문금액 합계는 다른 속성에서 계산해 만든 파생 속성입니다.
  4. 다중값 속성에 대한 처리로 가장 적절한 것은?
    ① 컬럼을 연락처1, 연락처2, 연락처3으로 늘린다
    ② 값들을 쉼표로 이어 한 컬럼에 넣는다
    ③ 별도의 엔터티로 분리하고 관계를 맺는다
    ④ 파생 속성으로 바꾼다
    ③. 다중값 속성은 별도 엔터티로 분리합니다. ①은 값이 넷이 되면 다시 무너지고, ②는 한 칸에 여러 값이 들어가 제1정규형을 어깁니다.
  5. 다음 세 행에서 COUNT(*), COUNT(점수), AVG(점수)의 값을 차례로 적으면?
    「점수 = 10, 점수 = 20, 점수 = NULL」
    ① 3, 3, 10
    ② 3, 2, 15
    ③ 2, 2, 15
    ④ 3, 2, 10
    ②. COUNT(*)는 NULL과 무관하게 행을 세므로 3, COUNT(점수)는 NULL 행을 빼므로 2, AVG(점수)는 NULL을 뺀 두 값의 평균이라 (10+20)/2=15(10+20)/2 = 15입니다.
  6. NULL에 대한 설명으로 옳지 않은 것은?
    ① 숫자 0이나 빈 문자열과 같지 않다
    ② WHERE 비고 = NULL은 결과 행을 반환하지 않는다
    ③ 산술 연산에 NULL이 끼면 결과는 NULL이다
    ④ SUM은 NULL을 0으로 바꿔 더한다
    ④. SUM은 NULL인 행을 계산에서 빼는 것이지 0으로 바꾸지 않습니다. 결과는 같아 보여도 AVG에서 분모가 달라지므로 구별해야 합니다.
  7. 도메인에 대한 설명으로 가장 적절한 것은?
    ① 엔터티가 가질 수 있는 인스턴스의 최대 개수
    ② 속성이 가질 수 있는 값의 범위와 타입
    ③ 엔터티 간 관계의 참여도
    ④ 주식별자를 구성하는 속성의 집합
    ②. 도메인은 데이터 타입·길이·제약조건을 아우르는 값의 범위입니다. ③은 카디널리티, ④는 식별자의 구성으로 다음 노트의 내용입니다.

NULL은 1과목에서 한 문항 정도로 짧게 나오지만 2과목의 함수·조인·서브쿼리 전반에 다시 등장합니다. 「연산에서는 전염되고 집계에서는 무시된다」 한 줄을 붙잡아 두면 뒤에서 헷갈릴 일이 크게 줄어듭니다.

SQL 개발자(SQLD) 시험 노트 전체 보기