DB_SQL_제약조건

BBBeom·2022년 8월 10일

DB

목록 보기
7/18

Constraint(제약조건)

테이블에 저장할 데이터를 제약하는 규칙

입력한 데이터와 제약조건을 비교해서 TRUE면 데이터가 입력되고
FALSE면 데이터가 입력되지 않는다

데이터베이스의 정확성/일관성을 유지하기위해 사용한다
-> 데이터의 무결성

  • 제약조건의 종류

    1. NOT NULL -> 지정한 열에 NULL을 허용하지 않는다
      (NULL을 제외한 데이터값의 중복은 허용)
    2. UNIQUE -> 지정한 열이 유일한 값을 가져야 한다(중복값이 허용안됨)
    3. PRIMARY KEY -> NOT NULL + UNIQUE(테이블의 컬럼중 하나만 지정가능)
    4. FOREIGN KEY -> 다른 테이블의 PRIMARY KEY컬럼을 참조하여 존재하는 값만 입력
    5. CHECK -> 설정한 조건식을 만족한 데이터만 입력(NOT NULL도 조건식이라고 보기때문에
      제약조건을 검색하면 제약조건의 타입(CONSTRAINT_TYPE)이 C라고 나온다)


1. NOT NULL

CREATE TABLE TABLE_NOTNULL(
LOGIN_ID VARCHAR2(20) NOT NULL,     /*생성할 컬럼에 NOT NULL이라는 제약조건을 걸엇다*/
LOGIN_PWD VARCHAR2(20) NOT NULL,
TEL VARCHAR2(20)
);

INSERT INTO TABLE_NOTNULL
VALUES('TEST_ID_01', NULL, NULL);	
/*LOGIN_PWD의 제약조건은 NULL이 올수 없기때문에 데이터를 넣을수가없다*/

제약조건이 달린 컬럼은 데이터의 입출력시에 지정한 제약조건이 붙는다

- 제약조건을 확인하기

SELECT OWNER, CONSTRAINT_NAME, CONSTRAINT_TYPE, TABLE_NAME
FROM USER_CONSTRAINTS;

SELECT * FROM USER_CONSTRAINTS;

출력된 결과값에서
CONSTRAINT_TYPE 을 보면 P, R, C 가있는데
각각 PRIMARY KEY, FOREIGN KEY, CHECK(NOT NULL) 이라는 뜻이다
U 는 UNIQUE다

CONSTRAINT_NAME -> 제약조건의 이름인데 시스템이 알아서 정해버린다
이를 내가 원하는 이름으로 정해줄 수 있다

- 제약조건에 이름 정해주기

CREATE TABLE TABLE_NOTNULL2(
LOGIN_ID VARCHAR2(20) CONSTRAINT TBLNN2_LOGID_NN NOT NULL,
LOGIN_PWD VARCHAR2(20) CONSTRAINT TBLNN2_LOGPW_NN NOT NULL,
TEL VARCHAR2(20)
);

/*CONSTRAINT TBLNN2_LOGID_NN 이부분이 생략되어 있으면 시스템이 이름을 정하지만
이렇게 지정해주면 CONSTRAINT_NAME을 나중에 검색하더라도 쉽게 알아볼수 있다
TBLNN2_LOGID_NN -> TABLE_NOTNULL2의 LOGID는 NOT NULL이다 라고 이름을 지어줫다*/

테이블을 생성할때 제약조건 앞에 CONSTRAINT 제약조건이름 으로
제약조건에 이름을 붙여서 생성할 수 있다

이름을 붙여주면 가독성이 올라가기 때문에 작업할때 편해진다


- 제약조건 수정하기

ALTER TABLE TABLE_NOTNULL2
MODIFY(TEL NOT NULL);	/*TEL은 아무 제약조건이 없었다 새로 NOT NULL이라는 조건이 생겼다*/

하지만 바꾸려고 하는 컬럼안의 데이터가 이미 NULL값이 존재한다면?
제약조건을 NULL로 바꿀수 없다
그럴경우 NULL데이터를 NULL이 아닌 데이터로 수정한후 제약조건을 걸어야한다

UPDATE TABLE_NOTNULL
SET TEL = '010-0000-0000'
WHERE TEL IS NULL;  /*NULL값의 DATA를 000으로 변경햇다*/

ALTER TABLE TABLE_NOTNULL
MODIFY(TEL NOT NULL);   /*다시 실행하면 잘 적용됬다*/

SELECT * FROM USER_CONSTRAINTS; /*조회해보면 TEL에 NOT NULL의 제약조건이 생긴걸 확인할수 있다*/

ALTER TABLE TABLE_NOTNULL
RENAME CONSTRAINT SYS_C0011066 TO TBLNN_TEL_NN; /*시스템이 정해준 CONSTRAINT NAME을
내가 원하는 이름으로 변경했다*/

제약조건의 이름수정하기 RENAME
제약조건의 조건수정하기 MODIFY


- 제약조건 삭제하기

ALTER TABLE TABLE_NOTNULL
DROP CONSTRAINT TBLNN_TEL_NN; /*CONSTRAINT명령을 사용할때 CONSTRANT NAME이 계속
사용이 되기때문에 USER_CONSTRAINTS 를 DESC 테이블 했던것처럼 체크해서 사용하면 된다*/


2. UNIQUE

열에 저장할 데이터의 중복을 허용하지 않는 제약조건
NULL값이 여러개가 있어도 데이터의 중복이 아닌 데이터가 없다는 뜻이므로
NULL값은 여러개가 들어올수가 있다

UNIQUE 제약조건을 걸면 자동으로 INDEX도 생성된다

UNIQUE 제약조건 생성하기

CREATE TABLE TABLE_UNIQUE(
LOGIN_ID VARCHAR2(20) UNIQUE,
LOGIN_PWD VARCHAR2(20) CONSTRAINT TBU_LOGPW_NN NOT NULL,
TEL VARCHAR2(20)
);

UNIQUE로 생성된 로그인 아이디 컬럼은 중복값이 들어가지지 않는다

INSERT INTO TABLE_UNIQUE(LOGIN_ID, LOGIN_PWD, TEL)
VALUES('TEST_ID_01', 'TEST_PW_01', 010-1234-5678);

두번 넣으려고하면 제약조건에 위배된다는 오류가 나온다

INSERT INTO TABLE_UNIQUE(LOGIN_ID, LOGIN_PWD, TEL)
VALUES('TEST_ID_02', 'TEST_PW_01', 010-1234-5678);

이름을 달리해주면 잘들어간다

  • NULL값의 중복허용
INSERT INTO TABLE_UNIQUE
VALUES(NULL, 'TEST_PW_01', 010-1234-5678);

이와같이 데이터를 입력하면 UNIQUE지만 계속 데이터가 들어간다

제약조건 수정하기

상황1. UNIQUE컬럼의 데이터를 수정하기

제약조건을 맞추면서 데이터를 수정하기때문에 다음과같은 상황이 발생할수있다

UPDATE TABLE_UNIQUE
SET LOGIN_ID = 'TEST_PW_01'
WHERE LOGIN_ID IS NULL;

NULL값이 여러개가 들어가있으면 데이터를 수정할때 데이터가 중복이 될수있다
UNIQUE를 쓸때 이를 조심해야한다
WHERE로 조건을 다른 컬럼에 적용시켜서 하나씩 바꿔줄수도 있겠지만
만약 다른 컬럼마저 구분이 안된다면 하나씩 수정은 불가능하다

상황2. 컬럼의 제약조건을 UNIQUE로 수정하기

ALTER TABLE TABLE_UNIQUE
MODIFY(TEL UNIQUE);

TEL 컬럼에 UNIQUE로 제약조건을 걸고 싶었지만
안에 있는 데이터를 봤더니 중복되는 데이터들이 있어서
UNIQUE제약조건에 위배되서 수정이 불가능 했다

중복되는 데이터를 먼저 수정을 해야 UNIQUE 제약조건도 수정이 가능하다

제약조건 삭제하기

마찬가지로 제약조건의 이름을 찾아서 삭제해줄 수 있다

ALTER TABLE TABLE_UNIQUE
DROP CONSTRAINT TBLUNQ_TEL_UNQ;

제약조건의 이름을 정해주어야하는 이유가 나오는데
만약 사용자가 지정하지 않고 SELECT * FROM USER_CONSTRAINTS; 을 해보면

SYS_C0011073
SYS_C0011068
SYS_C0011061

이런형태로 나오기때문에 내가 원하는 제약조건을 찾기가 힘들다 그래서 명명해주는것이 좋다



3. PRIMARY KEY

유일하게 하나만 있는 값 UNIQUE + NOT NULL
테이블당 하나의 컬럼에만 적용가능하다

자동으로 인덱스가 만들어진다

PRIMARY KEY 제약조건 생성하기

CREATE TABLE TABLE_PK(
TEST_LOGIN_ID VARCHAR2(20) CONSTRAINT TVLPK_LOGID_PK PRIMARY KEY,
TEST_LOGIN_PWD VARCHAR2(20) CONSTRAINT TVLPK_LIGPWD_NN NOT NULL,
TEST_TEL VARCHAR2(20)
);

SELECT * FROM USER_CONSTRAINTS; 로 제약조건을 찾으려고보니
지금까지 만든 제약조건이 너무 많아서 찾기 힘들어졌다 그럴때는

SELECT * FROM USER_CONSTRAINTS
WHERE TABLE_NAME LIKE'%TABLE_PK%';

이런식으로 테이블명을 지정해서 제약조건을 검색할 수 있다

조건을 검색해보면 자동으로 인덱스 까지 생긴걸 확인할수있다
인덱스 이름도 PK의 이름과 똑같다

INSERT INTO TABLE_PK
VALUES('TEST_ID', 'TEST_PWD', 1234-1234);
/*값을 두번 넣어보면 제약조건때문에 들어가지지 않는다*/

INSERT INTO TABLE_PK
VALUES(NULL, 'TEST_PWD', 1234-1234);
/*NULL로 넣어도 제약조건 때문에 들어가지지 않는다*/

다른 제약조건과 마찬가지로 수정, 삭제가 같은 방식으로 가능하다

ALTER TABLE 테이블
MODIFY(컬럼 제약조건);

ALTER TABLE 테이블
DROP CONSTRAINT 제약조건이름;

ALTER TABLE 테이블
RENAME CONSTRAINT 기존제약조건이름
TO 바꿀제약조건이름;

자주 사용하는 컬럼?
PRIMARY KEY는 데이터의 고유성을 보장하므로 ID 열에 자주 쓰인다

PRIMARY KEY는 테이블에 엔터티 무결성을 적용

ENTITY 엔터티
-> 실체/객체라는 의미
깊게 들어가면 좀더 많은 정보가 있지만 일단 이정도로 알아둘것
엔터티 무결성이라는건 객체가 정확하고 일관성있다는 뜻이다

  • PRIMARY KEY가 있는 테이블을 통째로 지우려고하면
    참조하고 있는 FOREIGN KEY의 테이블이 존재하는경우
    지워지지 않고 에러가 발생한다


4. FOREIGN KEY

다른 테이블과 관계를 맺어야 하는 제약조건

어떤 테이블에서 PRIMARY KEY 제약조건을 지정한 컬럼을
다른 테이블에서 FOREIGN KEY 제약조건으로 컬럼을 지정할수 있다

제약조건 생성하기

CREATE TABLE TABLE_FK(
TEST_LOGIN_ID VARCHAR2(20) CONSTRAINT TVLFK_LOGID_FK 
REFERENCES TABLE_PK(TEST_LOGIN_ID),
TEST_LOGIN_PWD VARCHAR2(20) CONSTRAINT TVLFK_LOGPWD_NN NOT NULL,
TEST_TEL VARCHAR2(20)
);

만드는법이 조금 다른데 FOREIGN KEY 라는 문구를 사용하지 않고
(문구를 사용해서 만드는 방법도 있다 지금 방법이 좀더 쉽다고 생각한다)
REFERENCES 부모테이블(PRIMARY KEY 컬럼) 형식으로 적어주면
해당컬럼이 자동으로 해당 PRIMARY KEY에 대한 FOREIGN KEY로 제약조건이 생긴다

KEY를 아주 많이 만들경우에는 문법이 길어질 수도 있지만
보통 KEY값은 그렇게 많은 경우가 없기때문에 큰 문제가 없다고 생각한다

  • 주의할점
    FOREIGN KEY는 REFERENCE할 PRIMARY KEY컬럼의 레코드가 존재하지 않을경우엔
    생성 자체가 불가능하다 PRIMARY KEY의 값이 하나이상 존재할경우에 생성할 수 있다


5. CHECK

해당 컬럼의 데이터에 사용자가 원하는 조건을 걸어서
TRUE일때는 데이터가 들어가고 FALSE면 못들어가는 제약조건

CREATE TABLE TABLE_CHECK(
TEST_LOGIN_ID VARCHAR2(20) CONSTRAINT TVLCK_LOGID_PK PRIMARY KEY,
TEST_LOGIN_PWD VARCHAR2(20) CONSTRAINT TVLCK_LOGPW_CK 
CHECK(LENGTH(TEST_LOGIN_PWD) > 3),
TEST_TEL VARCHAR2(20)
);

CHECK() 안에는 WHERE 절 뒤에오는 문법같은 형태의 조건절을 사용한다
하지만 BETWEEN같은 문법은 애초에 성립이 안되기 때문에 잘 골라서 사용해야한다

데이터의 무결성을 위해 자주 쓰일것 같다
제약조건을 잘 활용하면 엉뚱한 데이터가 들어가는 일을
미리 방지할수 있을것이다

  • 이미 제약조건이 걸려있는 컬럼에 제약조건을 MODIFY로 수정해 봤는데
    만약 CHECK로 제약이 걸려있는 컬럼에 NOT NULL제약조건을 하면
    하나의 컬럼에 두개의 제약조건이 생긴다
    PRIMARY KEY가 UNIQUE + NOT NULL 인것처럼
    다른 제약조건들도 추가가 가능 한것 같다(논리적 오류가 없는 선에서 가능하다)
    단 MODIFY로 생성한 제약조건은 이름을 정해주지 않았기에
    자동으로 시스템에서 명명한다

데이터베이스를 위한 데이터사전

데이터베이스를 통해 관리할 데이터를 저장하는 테이블
DB를 운영하는데 필요한 중요한 데이터를 보관한다

USER_XXX : 현재 데이터베이스 접속자가 소유한 객체정보
ALL_XXX : 접속자가 소유한 객체 또는 다른 사용자가 소유한 객체중 사용허가를 받은 객체
DBA_XXX : SYSTEM, SYS 사용자만 열람 가능한 테이블
V$_XXX : 성능 관련 정보

일반 개발자는 핵심적인 몇개 빼고는 사용할일이 드물다
(제약조건을 확인하기 위해서 사용한 USER_XXX가 데이터사전에 해당된다)
이정도가 있다고 알아만 두자

profile
BackEnd_BasketBall_Beom

0개의 댓글