1. 제약 조건


제약 조건(Constraint)이란, 데이터의 무결성을 지키기 위해 제한된 조건을 의미한다.

즉, 특정 데이터를 입력할 때 무조건적으로 입력되는 것이 아니라, 
어떠한 조건을 만족했을 때에만 입력되도록 제약을 할 수 있는 것이다.

예를 들어, 어떠한 쇼핑몰에 가입할 때 이미 가입한 주민등록번호로는 재가입이 되지 않는다.
그 이유는 주민등록번호 열에 동일한 것이 들어갈 수 없는 "제약 조건"이 설정되어 있기 때문이다.
이런 경우 주민등록번호에 중복이 불가능한 제약 조건(이 경우 보통 UNIQUE)이 들어 있을 것이다.

이 외에도 SQLServer는 아래와 같은 제약 조건들을 제공하고 있다.
  • Primary key 제약 조건
  • Foreign key 제약 조건
  • UNIQUE 제약 조건
  • CHECK 제약 조건
  • DEFAULT 정의


2. PK 제약 조건

테이블에 존재하는 많은 행의 데이터를 구분할 수 있는 식별자를 "기본 키(Primary key)"라고 부른다.

기본 키에 입력되는 값은 중복될 수 없으며, NULL 값이 입력될 수 없다.

기본 키로 생성한 것은 자동으로 클러스터형 인덱스가 생성된다.


  1. CREATE TABLE UserTable
  2. (
  3.     UserID CHAR(8) NOT NULL PRIMARY KEY,
  4.     Name NVARCHAR(10) NOT NULL,
  5.     -- 이하 열 생략
  6. )

이렇게 설정함으로써 UserID는 UserTable의 기본 키가 되었으며,
앞으로 입력되는 UserID는 당연히 중복될 수 없고, 비어(NULL) 있을 수도 없다.

모든 제약 조건은 이름을 가지게 되는데, 위와 같이 UserID 열에 대해 기본 키를 설정하고 나면,
"PK__UserTable__3214EC27060DEAE8" 등과 같이 알아볼 수 없는 이름을 가지게 된다.
이는 SQLServer가 제약 조건의 이름을 나름의 규칙을 가지고 알아서 설정해 버리기 때문이다.

UserTable에 PK가 설정되었다는 것까지는 알겠는데, 위와 같은 네이밍이면 어느 열이 PK인지 알아보기 쉽지 않다.

기본 키를 설정할 때 이름을 지정하려면 아래와 같이 CREATE TABLE시 작성하면 된다.

  1. CREATE TABLE UserTable
  2. (
  3.     UserID CHAR(8) NOT NULL CONSTRAINT PK_UserID PRIMARY KEY,
  4.     Name NVARCHAR(10) NOT NULL,
  5.     -- 이하 열 생략
  6. )

UserTable의 기본 키를 UserID 열로 정하되, PK_UserID라는 이름을 가지도록 하라는 것이다.


또한, 테이블에서 하나 이상의 열을 기본 키로 설정할 수 있다.
즉, N 개의 열을 묶어 기본 키로 설정할 수 있는 것이다.

SSMS에서 아래와 같이 복수의 컬럼을 엮어 기본 키로 설정할 수 있으며,



T-SQL의 CREATE TABLE문은 아래와 같이 작성하여 복수 열을 기본 키로 설정할 수 있다.

  1. CREATE TABLE UserTable
  2. (
  3.     UserID CHAR(8) NOT NULL,
  4.     Name NVARCHAR(10) NOT NULL,
  5.     -- 이하 열 생략
  6.     CONSTRAINT PK_UserID_Name PRIMARY KEY (UserID, Name)  
  7. )


3. FK 제약 조건

외래 키(Foreign Key) 제약 조건은 
두 테이블 사이의 관계를 선언함으로써, 데이터의 무결성을 보장해 주는 역할을 한다.

외래 키 관계를 설정하게 되면 하나의 테이블(외래 키 테이블)이 다른 테이블(기준 테이블)에 의존하게 된다.

'외래 키 테이블'에 데이터를 입력할 때는 꼭 '기준 테이블'을 참조해서 입력하므로,
반드시 '기준 테이블'에 존재하는 데이터만 입력이 가능하다.

또한, '외래 키 테이블'이 참조하는 '기준 테이블'의 열은 반드시 PK이거나 UNIQUE 제약 조건이 설정되어 있어야 한다.
이는 조금만 생각해보면, 지극히 당연한 제약이다.
A가 B를 참조하는 데 B가 여러 개 이면 어느 것을 참조해야 할 지 알 수 없기 때문이다.



  1. CREATE TABLE UserTable
  2. (
  3.     UserID CHAR(8) NOT NULL
  4.     CONSTRAINT PK_UserID PRIMARY KEY,
  5.     Name NVARCHAR(10) NOT NULL,
  6.     -- 이하 열 생략
  7. )
  8.  
  9. -- unnamed
  10. CREATE TABLE BuyTable
  11. (
  12.     UserID CHAR(8) NOT NULL
  13.     FOREIGN KEY REFERENCES UserTable(ID),
  14.     -- 이하 열 생략
  15. )
  16.  
  17. -- named
  18. CREATE TABLE BuyTable
  19. (
  20.     UserID CHAR(8) NOT NULL
  21.     CONSTRAINT FK_UserTable_ID FOREIGN KEY REFERENCES UserTable(ID),
  22.     -- 이하 열 생략
  23. )



헌데, 외래 키로 지정한 기준의 컬럼의 값이 변경되면 외래 키 테이블의 컬럼 값은 어떻게 처리할 것인가?

예를 들어, UserTable의 ID(PK) = 'KHD'인 값이 있고, BuyTable에도 ID(FK) = 'KHD'인 데이터들이 있다.
ID 변경 아이템 등을 사용하여 UserTable의 ID 'KHD'를 'KKHD'로 변경해야 한다면, 
BuyTable에 이미 존재하는 'KHD'들도 변경이 되어야만 외래 키 제약이 제대로 유지될 수 있다.

외래 키 옵션 중 ON UPDATE CASCADEON DELETE CASCADE라는 것이 있다.
  • ON UPDATE CASCADE : 기준 테이블의 데이터가 변경되었을 때 외래 키 테이블도 자동으로 변경
  • ON DELETE CASCADE : 기준 테이블의 데이터가 삭제되었을 때 외래 키 테이블의 데이터들도 자동으로 삭제

외래 키의 위 두가지 옵션에 대해 기본값은 ON UPDATE NO ACTION과 ON DELETE NO ACTION으로 지정되어 있다.
즉, 기준 테이블의 데이터가 변경/삭제되어도 외래 키 테이블에 자동적으로 변경/삭제를 해주지 않도록 되어 있다.

이를 변경하는 방법 역시 SSMS를 통한 방법과 T-SQL을 통한 방법 두 가지가 있다.

먼저 SSMS의 속성은 다음과 같이 변경이 가능하다.



기본적으로는 동작 안 함이 선택되어 있으며, CASCADE를 설정하고 싶으면 "계단식 배열"을 선택하면 된다.
(번역 참 구리다)

그리고 아래와 같이 작성하면 T-SQL을 통해서도 속성 변경이 가능하다.

  1. -- ON UPDATE CASCADE
  2. CREATE TABLE BuyTable
  3. (
  4.     UserID CHAR(8) NOT NULL
  5.     FOREIGN KEY REFERENCES UserTable(ID)
  6.     ON UPDATE CASCADE,
  7.     -- 이하 열 생략
  8. )
  9.  
  10. -- ON DELETE CASCADE
  11. CREATE TABLE BuyTable
  12. (
  13.     UserID CHAR(8) NOT NULL
  14.     CONSTRAINT FK_UserTable_ID FOREIGN KEY REFERENCES UserTable(ID)
  15.     ON DELETE CASCADE,
  16.     -- 이하 열 생략
  17. )


4. UNIQUE 제약 조건

UNIQUE 제약 조건은 중복되지 않는 유일함을 부여하고 싶을 때 사용하는 제약 조건이다.
PK와 얼핏 비슷해 보이지만, 네 가지 차이점이 존재한다.
  • UNIQUE는 유일하게 하나의 개체에 대해서만 NULL을 허용한다.
  • PK는 테이블에 하나만 존재 가능하나, UNIQUE 제약조건은 여러 개 설정이 가능하다.
  • PK는 자동으로 클러스터형 인덱스가 된다.

흔한 게임 DB의 유저 정보를 예로 들자면, 유저 식별 번호나 유일한 ID 등은 PK로 잡겠지만,
사용자별 E-Mail 주소나 닉네임에 대해서는 UNIQUE 제약조건을 부여할 수 있는 것이다.
이를 T-SQL로 설정하는 방법은 아래와 같다.

  1. -- unnamed
  2. CREATE TABLE UserTable
  3. (
  4.     -- ...
  5.     Email NVARCHAR(50) NOT NULL UNIQUE,
  6.     -- ...
  7. )
  8.  
  9. -- named
  10. CREATE TABLE UserTable
  11. (
  12.     -- ...
  13.     Email NVARCHAR(50) NOT NULL
  14.     CONSTRAINT UK_UserTable_Email UNIQUE,
  15.     -- ...
  16. )


5. CHECK 제약 조건

CHECK 제약 조건은 특정 조건들로 이루어진 수식을 통해 입력되는 데이터를 검증할 때 사용한다.

예를 들어, 음수값은 허용하지 않는다던지,
출생년도가 1900년 이후이고 현재 시점 이전이어야만 한다던지 등의 조건을 지정할 수 있는 것이다.
이를 T-SQL로 설정하려면 아래와 같이 코딩한다.

  1. -- unnamed
  2. CREATE TABLE #CKTable
  3. (
  4.     -- ...
  5.     Number INT NOT NULL
  6.     CHECK (Number >= 1 AND Number <= 10)
  7. )
  8.  
  9. -- named
  10. CREATE TABLE #CKTable
  11. (
  12.     -- ...
  13.     Number INT NOT NULL
  14.     CONSTRAINT CK_VALUE CHECK (Number >= 1 AND Number <= 10)
  15. )


6. DEFAULT 정의

DEFAULT는 값을 입력하지 않았을 때, 자동으로 입력되는 기본 값을 정의하는 방법이다.

  1. CREATE TABLE #DefaultTable
  2. (
  3.     BirthYear INT NOT NULL   DEFAULT YEAR(GETDATE()),
  4.     Addr NCHAR(2) NOT NULL   DEFAULT N'서울',
  5.     Height SMALLINT NOT NULL DEFAULT 172,
  6.     -- ...
  7. )

위 예제와 같이 DEFAULT 키워드를 사용하고, 각 컬럼의 데이터 형식에 맞는 기본값을 지정해 주면 된다.


7. 다음 문서

이 문서에서 T-SQL을 이용한 제약조건 설정은 모두 테이블을 생성할 때로 한정되어 설명되어 있다.

DB를 운영하다 보면, 이미 만들어진 테이블에 제약조건을 추가하거나, 삭제 또는 변경해야 할 일도 다반사이다.
특히 이미 데이터가 들어가 있는 테이블이라면 말이다.


'SQL > MS-SQL' 카테고리의 다른 글

PIVOT/ UNPIVOT  (0) 2017.09.21
제약 조건(Constraint) #2 (기존 테이블에 추가/삭제)  (0) 2017.09.20
테이블변수  (0) 2017.09.20
테이블 컬럼변경  (0) 2017.09.20
SELF JOIN  (0) 2017.09.19

+ Recent posts