* 제약 조건 종류
- 제약 조건이란?
: 테이블 열에 저장될 데이터의 특성, 조건을 지정한다.
ex) 로그인에 사용할 아이디, 이메일 주소 중복되지 않게 설정
✔️데이터 무결성(data integrity)
: 데이터베이스에 저장되는 데이터의 정확성과 일관성을 보장한다는 의미로 제약 조건이 데이터 무결성을 지키기 위한 안전장치로서 중요한 역할을 한다.
종류 | 설명 | |
영역 무결성 (domain integrity) |
열에 저장되는 값의 적정 여부를 확인. 자료형, 적절한 형식의 데이터, NULL 여부같은 정해 놓은 범위를 만족하는 테이터임을 규정 | |
개체 무결성 (entity integrity) |
테이블 데이터를 유일하게 식별할 수 있는 기본키는 반드시 값을 가지고 있어야 하며 NULL이 될 수 없고 중복될 수도 없음을 규정 | |
참조 무결성 (referential integrity) |
참조 테이블의 외래키 값은 참조 테이블의 기본키로서 존재해야 하며 NULL이 가능 |
* 빈값을 허락하지 않는 NOT NULL
- 지정된 열에 NULL 저장 불가 -> 반드시 열에 값이 존재해야만 한다.
- NULL외 데이터의 중복은 허용
- 테이블을 생성하며 제약 조건 지정
<예시>
- 테이블을 생성할 때 NOT NULL 설정
CREATE TABLE TABLE_NOTNULL (
LOGIN_ID VARCHAR2(20) NOT NULL,
LOGIN_PWD VARCHAR2(20) NOT NULL,
TEL VARCHAR2(20)
);
DESC TABLE_NOTNULL;
- 제약 조건이 NOT NULL인 열에 NULL값 입력
INSERT INTO TABLE_NOTNULL (LOGIN_ID, LOGIN_PWD, TEL)
VALUES('TEST_ID_01', NULL, '010-1234-5678');
=> LOGIN_PWD 열에 NULL값 입력 불가능
- 제약 조건이 없는 TEL열에 NULL 값 입력
INSERT INTO TABLE_NOTNULL(LOGIN_ID, LOGIN_PWD)
VALUES ('TEST_ID_01', '1234');
SELECT * FROM TABLE_NOTNULL;
=> TEL열에 NULL값 입력 가능
- NOT NULL 제약 조건이 지정된 열 데이터를 NULL값으로 업데이트
UPDATE TABLE_NOTNULL
SET LOGIN_PWD = NULL
WHERE LOGIN_ID = 'TEST_ID_01';
=> NULL값으로 업데이트 불가
- 제약 조건 확인
- USER_CONSTRAINTS 데이터 사전
<예시>
- 제약 조건 살펴보기(HR 계정)
SELECT OWNER, CONSTRAINT_NAME, CONSTRAINT_TYPE, TABLE_NAME
FROM USER_CONSTRAINTS;
=> 오라클에 의해 제약 조건의 이름이 자동으로 지정되었다.
- 제약 조건 이름 직접 지정
: CONSTRAINT 키워드 사용
- 테이블을 생성하며 제약조건 지정
- 제약 조건 이름 직접 지정
- 이미 생성한 테이블에 제약 조건 지정
<예시>
- 테이블 생성할 때 제약 조건 이름 지정
CREATE TABLE TABLE_NOTNULL2(
LOGIN_ID VARCHAR(20) CONSTRAINT TBLNN2_LGNID_NN NOT NULL,
LOGIN_PWD VARCHAR2(20) CONSTRAINT TBLNN2_LGNPW_NN NOT NULL,
TEL VARCHAR(20)
);
SELECT OWNER, CONSTRAINT_NAME, CONSTRAINT_TYPE, TABLE_NAME
FROM USER_CONSTRAINTS;
=> 지정한 이름으로 저장됨
- 이미 생성한 테이블에 제약 조건 지정
- NOT NULL 제약 조건 추가는 ALTER, MODIFY 키워드 사용
<예시>
- TEL 열에 NOT NULL 제약 조건 추가하기
ALTER TABLE TABLE_NOTNULL
MODIFY(TEL NOT NULL);
=> TEL열에 NULL값이 있기 때문에 NOT NULL 제약조건 충돌
- TEL 열 데이터 수정 및 NOT NULL 제약 조건 추가
-- 테이블 수정
UPDATE TABLE_NOTNULL
SET TEL = '010-1234-5678'
WHERE LOGIN_ID = 'TEST_ID_01';
-- 테이블 조회
SELECT * FROM TABLE_NOTNULL;
-- 테이블 제약조건 추가
ALTER TABLE TABLE_NOTNULL
MODIFY(TEL NOT NULL);
-- 제약조건 조회
SELECT OWNER, CONSTRAINT_NAME, CONSTRAINT_TYPE, TABLE_NAME
FROM USER_CONSTRAINTS;
=> TEL 데이터 바뀜
=> 테이블에 제약조건 지정 가능
=> 제약조건 추가됨
- 제약 조건에 이름 지정해서 추가
ALTER TABLE TABLE_NOTNULL2
MODIFY(TEL CONSTRAINT TBLNN_TEL_NN NOT NULL);
DESC TABLE_NOTNULL2;
- 이미 생성된 제약 조건 이름 변경
ALTER TABLE TABLE_NOTNULL2
RENAME CONSTRAINT TBLNN_TEL_NN TO TBLNN2_TEL_NN;
SELECT OWNER, CONSTRAINT_NAME, CONSTRAINT_TYPE, TABLE_NAME
FROM USER_CONSTRAINTS;
=> TABLENN_TEL_NN 에서 TBLNN2_TEL_NN으로 이름 변경됨
- 제약 조건 삭제
- ALTER 명령어에 DROP CONSTRAINT 키워드 사용
<예시>
- 제약 조건 삭제하기
ALTER TABLE TABLE_NOTNULL2
DROP CONSTRAINT TBLNN2_TEL_NN;
DESC TABLE_NOTNULL2;
=> TEL 열 제약조건 삭제됨
* 중복되지 않는 값 UNIQUE
- 지정된 열에 중복 데이터 저장 불가
- NULL 저장은 가능
- 테이블을 생성하며 제약 조건 지정
- CREATE 문 사용
<예시>
- 테이블 생성할 때 제약 조건 지정
CREATE TABLE TABLE_UNIQUE(
LOGIN_ID VARCHAR2(20) UNIQUE,
LOGIN_PWD VARCHAR2(20) NOT NULL,
TEL VARCHAR2(20)
);
DESC TABLE_UNIQUE;
- 제약 조건 확인
<예시>
- USER_CONSTRAINTS 데이터 사전 뷰로 제약 조건 확인
SELECT OWNER, CONSTRAINT_NAME, CONSTRAINT_TYPE, TABLE_NAME
FROM USER_CONSTRAINTS
WHERE TABLE_NAME = 'TABLE_UNIQUE';
=> TBALE_UNIQUE 테이블의 제약 조건만 조회
- 중복을 허락하지 않는 UNIQUE
<예시>
- 중복 값 저장 안되는 LOGIN_ID열 확인
INSERT INTO TABLE_UNIQUE(LOGIN_ID, LOGIN_PWD, TEL)
VALUES('TEST_ID_01', 'PWD01', '010-1234-5678');
SELECT * FROM TABLE_UNIQUE;
INSERT INTO TABLE_UNIQUE(LOGIN_ID, LOGIN_PWD, TEL)
VALUES('TEST_ID_01', 'PWD01', '010-1234-5678');
=> 중복 데이터 추가 불가능
- 중복이 아닌 값 입력
INSERT INTO TABLE_UNIQUE(LOGIN_ID, LOGIN_PWD, TEL)
VALUES('TEST_ID_02', 'PWD01', '010-2345-6789');
SELECT * FROM TABLE_UNIQUE;
=> LOGIN_PWD는 NOT NULL 조건만 지정되어 있어 중복 허용됨
- UNIQUE 제약 조건과 NULL 값
- UNIQUE 제약 조건은 열 값의 중복은 허용하지 않지만 NULL저장은 가능하다.
- NULL값은 값을 비교할 수 없기 때문에 데이터 중복 의미를 부여할 수 없다.(따라서 여러개 NULL존재 가능)
<예시>
- UNIQUE 제약 조건 있는 열에 NULL 값 입력
INSERT INTO TABLE_UNIQUE(LOGIN_ID, LOGIN_PWD, TEL)
VALUES('NULL', 'PWD01', '010-2345-6789');
SELECT * FROM TABLE_UNIQUE;
- 데이터 수정(LOGIN_ID 중복)
UPDATE TABLE_UNIQUE
SET LOGIN_ID = 'TEST_ID_01'
WHERE LOGIN_ID IS NULL;
=> 데이터 중복이므로 수정 불가
- 테이블 생성하며 제약 조건 이름 직접 지정
- 이름 지정 가능
- 이름 지정 안할경우 오라클이 자동으로 지정
<예시>
- 테이블 생성할 때 UNIQUE 제약 조건 설정
-- 테이블 생성
CREATE TABLE TABLE_UNIQUE2(
LOGIN_ID VARCHAR2(20) CONSTRAINT TBLUNQ2_LGNID_UNQ UNIQUE,
LOGIN_PWD VARCHAR2(20) CONSTRAINT TBLUNQ2_LGNPW_NN NOT NULL,
TEL VARCHAR2(20)
);
-- 제약 조건 확인
SELECT OWNER, CONSTRAINT_NAME, CONSTRAINT_TYPE, TABLE_NAME
FROM USER_CONSTRAINTS
WHERE TABLE_NAME LIKE 'TABLE_UNIQUE%';
- 이미 생성한 테이블에 제약 조건 지정
- ALTER 명령어로 제약 조건 추가 가능
<예시>
- 이미 생성한 테이블 열에 UNIQUE 제약 조건 추가
ALTER TABLE TABLE_UNIQUE
MODIFY(TEL UNIQUE);
=> 이미 TEL열이 중복 데이터가 있기 때문에 오류가 뜬다.
- TEL 열 값 모두 NULL값으로 변경
UPDATE TABLE_UNIQUE
SET TEL = NULL;
SELECT * FROM TABLE_UNIQUE;
- TEL 값에 UNIQUE 제약 조건 설정
ALTER TABLE TABLE_UNIQUE
MODIFY(TEL UNIQUE);
- UNIQUE 제약 조건 이름 직접 지정
-- 제약 조건 이름 지정
ALTER TABLE TABLE_UNIQUE2
MODIFY(TEL CONSTRAINT TBLUNQ_TEL_UNQ UNIQUE);
-- 제약 조건 이름 수정
ALTER TABLE TABLE_UNIQUE2
RENAME CONSTRAINT SYS_C007010 TO TBLUNQ_TEL_UNQ UNIQUE);
-- 제약 조건 조회
SELECT OWNER, CONSTRAINT_NAME, CONSTRAINT_TYPE, TABLE_NAME
FROM USER_CONSTRAINTS
WHERE TABLE_NAME LIKE 'TABLE_UNIQUE%';
=> 제약 조건 이름 오라클에서 지정해준 이름(SYS_C007010)에서 TBLUNQ_TEL_UNQ로 변경됨
- 제약 조건 삭제
ALTER TABLE TABLE_UNIQUE2
DROP CONSTRAINT TBLUNQ_TEL_UNQ;
* 유일하게 하나만 있는 값 PRIMARY KEY
- 지정된 열에 중복 데이터 저장 불가
- NULL 저장 불가
- 자동으로 인덱스 생성
- NOT NUL제약 조건과 UNIQUE제약 조건이 합쳐진 형태
- 테이블 생성하며 제약 조건 지정
<예시>
- 테이블 생성할 때 특정 열에 PRIMARY KEY 설정
CREATE TABLE TABLE_PK(
LOGIN_ID VARCHAR2(20) PRIMARY KEY,
LOGIN_PWD VARCHAR2(20) NOT NULL,
TEL VARCHAR2(20)
);
DESC TABLE_PK;
SELECT OWNER, CONSTRAINT_NAME, CONSTRAINT_TYPE, TABLE_NAME
FROM USER_CONSTRAINTS
WHERE TABLE_NAME LIKE 'TABLE_PK%';
- 인덱스 확인
SELECT INDEX_NAME, TABLE_OWNER, TABLE_NAME
FROM USER_INDEXES
WHERE TABLE_NAME LIKE 'TABLE_PK%';
=> SYS_C007014 인덱스 생성됨
- 테이블 생성하며 제약 조건 이름 직접 지정
<예시>
- 제약 조건 이름 직접 지정해 테이블 생성
CREATE TABLE TABLE_PK2(
LOGIN_ID VARCHAR2(20) CONSTRAINT TBLPK2_LGNID_PK PRIMARY KEY,
LOGIN_PWD VARCHAR2(20) CONSTRAINT TBLPK2_LGNPW_NN NOT NULL,
TEL VARCHAR2(20)
);
DESC TABLE_PK2;
=> PRIMARY KEY의 제약조건은 NOT NULL도 있다
- 제약 조건 / 인덱스 조회
-- 제약 조건 조회
SELECT OWNER, CONSTRAINT_NAME, CONSTRAINT_TYPE, TABLE_NAME
FROM USER_CONSTRAINTS
WHERE TABLE_NAME LIKE 'TABLE_PK%';
-- 인덱스 조회
SELECT INDEX_NAME, TABLE_OWNER, TABLE_NAME
FROM USER_INDEXES
WHERE TABLE_NAME LIKE 'TABLE_PK%';
- TABLE_PK 테이블에 데이터 입력
-- 데이터 입력
INSERT INTO TABLE_PK(LOGIN_ID, LOGIN_PWD, TEL)
VALUES('TEST_ID_01', 'PWD01', '010-1234-5678');
-- 테이블 조회
SELECT * FROM TABLE_PK;
-- UNIQUE 제약 조건인 중복 오류가 발생
INSERT INTO TABLE_PK(LOGIN_ID, LOGIN_PWD, TEL)
VALUES('TEST_ID_01', 'PWD02', '010-2345-6789');
=> LOGIN_ID가 중복되므로 오류 발생(UNIQUE 제약 조건)
- PRIMARY KEY 제약 조건 지정한 열 확인(NULL 입력할 때)
<예시>
- NULL값을 명시적으로 입력
-- NULL 값 명시적 입력
INSERT INTO TABLE_PK(LOGIN_ID, LOGIN_PWD, TEL)
VALUES(NULL, 'PWD02', '010-2345-6789');
-- NULL 값 암시적 입력
INSERT INTO TABLE_PKLOGIN_PWD, TEL)
VALUES('PWD02', '010-2345-6789');
=> NULL값을 허용하지 않는다. (NOT NULL)
✔️열 바로 옆에 제약조건을 지정하는 형식
- 인라인 또는 열 레벨 제약조건
- 테이블 레벨 제약 조건 : NOT NULL 제약조건 제외한 제약조건 지정 가능
<예시>
CREATE TABLE TABLE_NAME(
COL1 VARCHAR2(20),
COL2 VARCHAR2(20),
COL3 VARCHAR2(20),
PRIMARY KEY (COL1),
CONSTRAINT CONSTRAINT_NAME UNIQUE(COL2)
);
* 다른 테이블과 관계를 맺는 FOREIGN KEY
- 다른 테이블의 PRIMARY KEY를 참조
- 참조하고 있는 키의 데이터와 NULL만 저장 가능
- 유의점 : 참조하는 테이블 열에 해당하는 컬럼 데이터 필요
<예시>
- EMP 테이블, DEPT 테이블 제약 조건 조회
SELECT OWNER, CONSTRAINT_NAME, CONSTRAINT_TYPE, TABLE_NAME, R_OWNER, R_CONSTRAINT_NAME
FROM USER_CONSTRAINTS
WHERE TABLE_NAME IN('EMP', 'DEPT');
CONSTRAINT_TYPE : R => 외래키를 의미하며 DEPT는 DEPT테이블의 PK인 DEPTNO 열 참조
- FK가 참조하는 열에 존재하지 않는 부서번호 데이터 입력
INSERT INTO EMP(EMPNO, ENMAE, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
VALUES(9999, '홍길동', 'CLERK', '7788', TO_DATE('2017/04/30', 'YYYY/MM/DD'), 1200, NULL, 50);
=> 존재하지 않는 50번 부서번호 때문에 제약 조건(참조하고 있는 키의 데이터, NULL만 저장 가능)으로 인해 오류가 뜬다.
- FOREIGN KEY 지정
- 기본 형식
CREATE TABEL 테이블 이름(
...(다른 열 정의),
열 자료형 CONSTRAINT [제약 조건 이름] REFERENCES 참조테이블(참조할 열)
);
=> 제약 조건 이름 지정 안해도 정의 가능
<예시>
- DPET_FK 테이블 생성
CREATE TABLE DEPT_FK(
DEPTNO NUMBER(2) CONSTRAINT DEPTFK_DEPTNO_PK PRIMARY KEY,
DNAME VARCHAR2(14),
LOC VARCHAR2(13)
);
- EMP_FK 테이블 생성
CREATE TABLE EMP_FK(
EMPNO NUMBER(4) CONSTRAINT EMPFK_EMPNO_PK PRIMARY KEY,
ENAME VARCHAR2(10),
JOB VARCHAR2(9),
MGR NUMBER(4),
HIREDATE DATE,
SAL NUMBER(7,2),
COMM NUMBER(7,2),
DEPTNNO NUMBER(2) CONSTRAINT EMPFK_DEPTNO_FK REFERENCES DEPT_FK (DEPTNO)
);
DESC EMP_FK;
- DEPTNO 데이터가 아직 DEPT_FK 테이블에 없을 때 EMP_FK 테이블에 데이터 삽입
INSERT INTO EMP_FK
VALUES(9999, 'TEST_ENAME', 'TEST_JOB', NULL, TO_DATE('2001/01/01', 'YYYY/MM/DD'),
3000, NULL, 10);
=>
- DEPT_FK에 데이터 삽입
INSERT INTO DEPT_FK
VALUES(10, 'TEST_DNAME', 'TEST_LOC');
SELECT * FROM DEPT_FK;
- EMP_FK 테이블에 데이터 삽입(DEPT_FK테이블에 DEPTNO 데이터 존재)
INSERT INTO EMP_FK
VALUES(9999, 'TEST_ENAME', 'TEST_JOB', NULL, TO_DATE('2001/01/01', 'YYYY/MM/DD'),
3000, NULL, 10);
SELECT * FROM EMP_FK;
- FOREIGN KEY로 참조 행 데이터 삭제하기
- DEPT_FK 테이블의 10번 부서 데이터 삭제하기
DELETE FROM DEPT_FK
WHERE DEPTNO = 10;
=> 현재 DEPT_FK 테이블에는 10번 부서 데이터가 저장되어 있고 EMP_FK 테이블에는 10번 부서를 참조하는 데이터가 있다.
=> 따라서 자식 레코드(DEPTNO)의 값을 참조하는 데이터가 존재하기 때문에 오류가 발생한다.
- 참조하는 데이터가 존재하는 테이블의 데이터를 삭제하는 방법
1. 현재 삭제하려는 열 값을 참조하는 데이터를 먼저 삭제한다.
ex) EMP_FK 테이블의 DEPTNO가 10번인 데이터를 삭제한 후 DEPT_FK 테이블의 10번 부서 삭제
2. 현재 삭제하려는 열 값을 참조하는 데이터를 수정한다. EMP.DEPTNO <- NULL
ex) EMP_FK 테이블의 DEPTNO가 10번인 데이터를 다른 부서 번호 또는 NULL로 변경한 후 DEPT_FK 테이블의 10번 부서 삭제
3. 현재 삭제하려는 열을 참조하는 자식테이블의 FK 제약 조건을 해제한다.
=> 위 세가지 방법은 삭제할 데이터를 참조하는 데이터의 수정 또는 삭제 작업을 선행해야 하므로
다소 귀찮은 작업이 될 수 있음 (따라서 제약 조건 처음 지정할 때 추가 옵션을 지정)
- 제약 조건을 처음 지정할 때 추가 옵션을 지정하는 방법
1. 열 데이터를 삭제할 때 이 데이터를 참조하고 있는 데이터도 함께 삭제
CONSTRAINT [제약 조건 이름] REFERENCES 참조 테이블(참조할 열) ON DELETE CASCADE
ex) DEPT_FK 테이블의 DEPTNO열 값이 10인 데이터를 삭제하면 이를 참조하는 EMP_FK테이블의 DEPTNO 열 값이 10인 데이터도 함께 삭제
2.열 데이터를 삭제할 때 이 데이터를 참조하는 데이터를 NULL로 수정
CONSTRAINT [제약 조건 이름] REFERENCES 참조 테이블(참조할 열) ON DELELTE SET NULL
ex) DEPT_FK 테이블의 DEPTNO 열 값이 10인 데이터를 삭제하면 이를 참조하는 EMP_FK 테이블의 DEPTNO 열 값이 10인 데이터를 NULL로 수정
* 데이터 형태와 범위를 정하는 CHECK
: 열에 저장할 수 있는 값의 범위 또는 패턴을 정의할 때 사용
<예시> 암호가 3글자 이상 입력시만 등록되게 하기
- 테이블을 생성할 때 CHECK 제약 조건 설정
CREATE TABLE TABLE_CHECK(
LOGIN_ID VARCHAR2(20) CONSTRAINT TBLCK_LOGINID_PK PRIMARY KEY,
LOGIN_PWD VARCHAR2(20) CONSTRAINT TBLCK_LOGINPW_CK CHECK (LENGTH(LOGIN_PWD)>3),
TEL VARCHAR2(20)
);
DESC TABLE_CHECK;
- CHECK 제약 조건 확인
-- CHECK 제약 맞지 않는 예
INSERT INTO TABLE_CHECK
VALUES('TEXT_ID', '123', '010-1234-5678');
-- CHECK 제약 맞는 예
INSERT INTO TABLE_CHECK
VALUES('TEXT_ID', '1234', '010-1234-5678');
-- 데이터 입력 완료
-- 조회
SELECT OWNER, CONSTRAINT_NAME, CONSTRAINT_TYPE, TABLE_NAME
FROM USER_CONSTRAINTS
WHERE TABLE_NAME LIKE 'TABLE_CHECK';
* 기본값을 정하는 DEFAULT
: 저장할 값이 지정되지 않읐을 경우에 기본값(default)을 지정
<예시>
- 테이블 생성할 때 DEFAULT 제약 조건 설정
CREATE TABLE TABLE_DEFAULT(
LOGIN_ID VARCHAR2(20) CONSTRAINT TBLCK2_LOGINID_PK PRIMARY KEY,
LOGIN_PWD VARCHAR2(20) DEFAULT '1234',
TEL VARCHAR2(20)
);
DESC TABLE_DEFAULT;
- DEFAULT로 지정한 기본값이 입력되는 INSERT문 확인
-- 명시적 NULL값 지정
INSERT INTO TABLE_DEFAULT VALUES ('TEST_ID', NULL, '010-1234-5678');
-- LOGIN_PWD에 기본값이 들어감
INSERT INTO TABLE_DEFAULT (LOGIN_ID, TEL) VALUES ('TEST_ID2', '010-1234-5678');
SELECT * FROM TABLE_DEFAULT;
✔️제약 조건 비활성화 / 활성화
: 신규 기능 개발이나 테스트 같은 특정 업무를 수행해야 할 때 제약조건이 걸림돌이 되는 경우에 사용
- 비활성화 - DISABLE절
ALTER TABLE 테이블 이름
DISABLE [NOVALIDATE / VALIDATE(선택)] CONSTRAINT 제약조건이름;
- 활성화 - ENABLE절
ALTER TABLE 테이블 이름
ENABLE [NOVALIDATE / VALIDATE(선택)] CONSTRAINT 제약조건이름;
'개발 공부 > Oracle' 카테고리의 다른 글
[Oracle] - 사용자, 권한, 롤 관리 (0) | 2023.12.11 |
---|---|
[Oracle] - 객체 종류 (0) | 2023.12.08 |
[Oracle] - 데이터 정의어 (0) | 2023.12.08 |
[Oracle] - 트랜잭션 제어와 세션 (0) | 2023.12.07 |
[Oracle] - 데이터 조작어 (0) | 2023.12.06 |