본문
- 제약조건(Constraint) : 컬럼마다 정하는 규칙
테이블에 올바른 데이터만 입력받고 잘못된 데이터는 들어오지 못하도록 함
1. 제약조건의 종류
조건 이름 |
의 미 |
NOT NULL |
NULL값이 입력되지 못함 |
UNIQUE |
중복된 값이 입력되지 못함 |
PRIMARY KEY |
NOT NULL + UNIQUE의 의미를 가짐 테이블 내에서 데이터들끼리의 유일성을 보장하는 컬럼에 설정할 수 있으며 테이블 당 1개만 설정할 수 있음 |
FOREIGN KEY |
다른 테이블의 칼럼을 참조해서 무결성 검사를 하게 됨 |
CHECK |
이 조건으로 설정된 값만 입력을 허용하고 나머지는 거부 |
- 위의 제약 조건은 컬럼별로 설정
- Primary Key를 제외한 나머지 제약조건들은 하나의 제약 조건이 여러 컬럼에 중복으로 설정 할 수 있고
하나의 컬럼에 여러 개의 제약조건들이 중복으로 설정 할 수 있음
- 어떤 컬럼에 UNIQUE 제약조건이나 Primary Key 제약조건을 설정하게 되면 해당 컬럼에 데이터는
서로 중복이 되지 않는 다는 뜻
- Foreign Key를 제외한 나머지 4개는 한 개의 테이블에 설정되지만 Foreign Key는 두 개의 테이블에 동시에 설정 됨
- 사원테이블에 입력이 될 때 부서 번호를 부서 테이블의 부서 번호 컬럼을 확인 한 후 존재하면 입력을 허용하고,
존재하지 않는다면 에러를 발생하고 입력을 거부하게 설정
- 정보를 제공해 주는 쪽 : 부서테이블(부모 테이블, Parent Table)
- 정보를 받는 쪽 : 사원테이블(자식테이블, Child Table)
- 부모 테이블쪽에 참조되는 컬럼에 설정되는 제약조건을 Reference Key(참조키)
- 자식 테이블쪽에 참조되는 컬럼에 설정되는 제약조건을 Foreign Key(외래키)라고 부름
- 참조키 제약조건은 자식 테이블에 데이터가 입력되기 위해서 부모 테이블의 특정 컬럼을 조사한 후
해당 데이터가 있을 경우 입력 허가.
- 부모 테이블의 데이터를 변경하려면 해당 부모 데이터를 참조하는 자식 테이블의 데이터가 없어야 함
- 참조키 제약조건을 설정할 때는 자식 테이블과 부모 테이블의 해당 컬럼에 반드시 적절한 인덱스를 생성하길 권장함
2. 각 제약 조건의 설정 방법
1) 테이블 생성시에 동시에 설정하기
SCOTT> CREATE TABLE emp3 |
SCOTT> CREATE TABLE emp4 |
- 두가지 방법은 동일한 효과를 냄, 차이점은 각 제약 조건의 이름을 직접 지정하느냐 안 하느냐의 차이
- 뒤에서 제약조건을 비활성화 / 활성화 / 삭제하는 등의 관리 작업을 하려면 해당 제약조건의 이름을 알고 있어야 한다.
그래서 제약 조건을 생성 할 때 위의 방법처럼 제약 조건의 이름을 직접 지정하는 것을 권장
아래처럼 제약조건의 종류만 적고 이름을 적지 않게 되면 오라클이 자동으로 이름을 결정하게 되는데
찾기가 불편한 부분이 많음
이렇게 설정된 제약조건들은 딕셔너리에 저장되어 있으며 데이터가 입력되기 전에 참조
2) 테이블 생성 후 추가하기
- 위에서 생성한 emp4 테이블의 name 컬럼에 UNIQUE 제약 조건 추가 SCOTT> ALTER TABLE emp4 |
- emp4 테이블의 Area 컬럼에 NOT NULL 제약 조건 추가 SCOTT> ALTER TABLE emp4
|
- 위 예에서 보듯이 NULL ↔ NOT NULL 로 변경하는 것은
ADD CONSTRAINT 명령어로 하는 것이 아니라 기본값으로 허용되어 있는 NULL을 NOT NULL로 변경하는 것이기
때문에 MODIFY 키워드를 사용해서 변경
- emp4테이블의 no컬럼이 emp2테이블의 empno컬럼의 값을 참조하도록 참조키 제약 조건 설정 (emp4 테이블이 자식테이블입니다) SCOTT> ALTER TABLE emp4 |
- 이렇게 참조키 제약조건을 설정하실 때 주의 사항
: 부모 테이블 쪽에 설정되는 컬럼이 Primary Key 이거나 Unique Key가 설정되어 있어야 한다
SCOTT> ALTER TABLE emp4
|
- FOREIGN KEY를 설정 후 부모 테이블 의 데이터를 지우고 싶은데 만약 자식테이블에서 부모테이블의 해당 데이터를
참조하고 있을 경우 지울 수가 없음
- 이럴 경우를 대비해서 FOREIGN KEY를 생성할 때 ON DELETE CASCADE 옵션을 줄 수 있음
이 옵션을 주면 부모테이블의 데이터가 지워지면 자식 테이블의 데이터도 함께 지우라는 의미가 됨
- ON DELETE SET NULL이란 옵션도 줄 수 있는 데 이 옵션은 부모테이블의 데이터가 지워질 경우 자식테이블의 값을
NULL로 설정
Step 1. 연습용 테이블을 생성합니다. SCOTT> create table c_test1 (
SCOTT> alter table c_test1
SCOTT> alter table c_test1 SCOTT> insert into c_test2 values (10,'AAAA');
SCOTT>insert into c_test1 values (3,'cherry',30);
Step 3. on delete cascade 테스트를 수행합니다. SCOTT> insert into c_test1 values (4,'peach',40); - parent key not found
1 apple 10
2 banana 20
Step 4. on delete set null 테스트를 수행합니다. SCOTT> alter table c_test1 drop constraint ctest1_deptno_fk;
2 banana 20
20 banana 30 cherry
2 banana ← 이 부분이 Null로 변경 3 cherry 30
|
자식 테이블의 deptno 컬럼에 not Null 속성이 설정되어 있는 상태에서 Foreign Key가 on delete set null 로 생성되면?!
Step 1. 자식테이블의 deptno 에 not null 속성을 설정합니다. SCOTT> alter table c_test1 (기존에 null 값이 있어서 변경할 수 없다는 뜻)
2 banana
2 banana 30
(정상적으로 자식 테이블의 deptno 컬럼에 not null이 설정됨) SCOTT> select * from c_test2;
( 부모 테이블을 지우려고 시도했더니 자식 테이블(c_test1) 을 null 로 update 할 수 없다고 에러가 나고 작업이 수행되지 않음이 확인 됨) |
3. 제약조건 관리하기
- 테이블의 컬럼에 설정되는 각 제약조건들은 어떤 필요에 의해서 일시적으로 DISABLE / ENABLE할 수 있음
ex) 예를 들어 이미 검증된 대량의 데이터를 테이블에 입력 할 경우는 데이터를 입력할 때 제약조건을 다시 검사 할 필요가
없다. 이럴 경우 제약조건을 임시로 DISABLE 해 둔 후 빠르게 데이터를 입력하고 입력이 완료되면
다시 ENABLE 하는 등의 작업을 많이 함
1) 제약 조건 DISABLE하기
: DISABLE 옵션은 NOVALIDATE와 VALIDATE 두 가지가 있음
- NOVALIDATE 옵션은 해당 제약조건이 없어서 데이터가 전부 들어온다는 뜻
(1) DISABLE NOVALIDATE 사용하기
SCOTT> INSERT INTO test_novalidate VALUES(1,'DDD'); (Primary Key 가 설정되어 있는 컬럼이므로 중복된 데이터 입력 안됨) SCOTT> ALTER TABLE test_novalidate
|
- DISABLE NOVALIDATE로 제약조건을 DISABLE하게 되면 CONSTRAINT가 없는 것과 동일하게 작동
(3) DISABLE VALIDATE 옵션 설정 후 다른 컬럼 내용 변경하기 Test_validate 테이블에 name 컬럼에 설정되어 있던 NOT NULL 제약조건이 DISABLE VALIDATE 되어 있는 상태에서 다른 컬럼에 데이터를 입력 SCOTT> INSERT INTO test_validate VALUES(4,'DDD');
|
- 위 테스트 결과 DISABLE VALIDATE 옵션은 결과적으로 테이블의 내용을 변경 할 수 없도록 함
- 위 테스트는 INSERT만 했지만 UPDATE나 DELETE 또한 동일한 결과를 볼 수 있음
- DISABLE 의 기본 옵션 : NOVALIDATE
- PRIMARY KEY나 UNIQUE 제약조건을 DISABLE 할 경우 생성되어 있던 UNIQUE INDEX 가 자동으로 삭제됨
2) 제약 조건 ENABLE하기
- DISABLE되어 있던 제약조건을 ENABLE하는 방법도 NOVALIDATE / VALIDATE 두 가지가 있음
- ENABLE NOVALIDATE는 제약조건을 ENABLE하는 시점까지 테이블에 들어 있는 데이터는 검사하지 않고
ENABLE 한 시점 이후부터 입력되는 데이터만 제약조건을 적용하여 검사하는 옵션
- ENABLE VALIDATE는 제약조건을 ENABLE하는 시점까지 테이블에 입력되어 있던 모든 데이터를 전부 검사하며
신규로 입력되는 데이터도 전부 검사하는 옵션
- 해당 제약조건을 ENABLE VALIDATE하게 되면 오라클이 해당 테이블에 데이터가 변경되지 못하도록(기존 데이터를
검사해야 하므로) LOCK을 설정
- 만약 검사도중에 제약조건을 위반하는 값이 발견되면 에러를 발생하면서 제약조건 ENABLE 작업을 취소
그렇게 되면 DBA나 사용자가 그 위반되는 데이터를 찾아서 적절하게 조치 후 다시 ENABLE 작업을 반복해서 시도해야 함
문제는 그 위반되는 데이터를 일일이 찾아서 조치를 해줘야 한다는 것
데이터가 많은 테이블은 데이터 이전 후 검증하는 데 시간이 아주 오래 걸릴 수 있습니다. 기본값이 ENABLE VALIDATE
- 이런 문제를 조금이라도 해결하기 위해 ENABLE VALIDATE 일 경우 사용할 수 있는 EXCEPTIONS라는 테이블이 존재
이 테이블에 위반 사항을 저장하게 설정하면 한결 쉽게 ENABLE 작업을 하실 수 있음!!
테스트용 테이블 test_enable 에 데이터를 입력
SCOTT> INSERT INTO test_enable VALUES(1,'AAA');
|
해당 제약조건을 DISABLE로 변경 후 다시 입력해 보겠습니다
SCOTT> ALTER TABLE test_enable
|
위 테스트 결과로 지금 test_enable 의 테이블에는 잘못된 데이터가 들어가 있다.
이 상태에서 제약 조건을 ENABLE
(1) ENABLE NOVALIDATE로 name 컬럼 제약조건 ENABLE하기 SCOTT> ALTER TABLE test_enable
|
- 위 테스트 결과를 보면 test_enable 테이블의 name 컬럼에 NOT NULL 제약 조건이 설정되어 있음에도 불구하고
3행의 NULL 값의 데이터가 입력되어 있음이 확인됨
즉, ENABLE NOVALIDATE 옵션은 ENABLE 시점에 테이블에 입력되어 있던 기존 데이터는 검사를 하지 않기 때문에
이런 현상이 생김 그러나 ENABLE 후 입력하는 값은 에러가 나고 입력이 안됨을 볼 수 있다
- 앞에서 살펴본 바와 같이 ENABLE NOVALIDATE는 신규로 입력되는 데이터만 검사함
(2) ENABLE VALIDATE로 name 컬럼 제약조건 ENABLE하기 SCOTT> ALTER TABLE test_enable
|
- 위 결과처럼 테이블에 잘못된 데이터가 들어가 있기 때문에 ENABLE VALIDATE를 할 수 없음
이럴 때 문제가 되는 행을 찾아서 수정해야 하는데 데이터가 많을 경우 일일이 그 행을 찾기가 힘들 때가 많음
이렇게 ENABLE VALIDATE 할 때 문제가 되는 행을 별도의 테이블에 저장해서 문제 행을 쉽게 찾을 수 있도록
해 주는 기능이 EXCEPTIONS 테이블!!(이 기능은 사용자가 별도로 생성하고 설정해야 함)
3) EXCEPTIONS 테이블을 사용하여 ENABLE VALIDATE 하기
Step 1. SYS계정으로 exceptions table 을 생성 SYS> @?/rdbms/admin/utlexcpt.sql ← ?는 $ORACLE_HOME 디렉토리를 의미합니다.
SYS> CREATE TABLE scott.tt550
SYS> ALTER TABLE scott.tt550 DISABLE CONSTRAINT tt550_nn;
SYS> INSERT INTO scott.tt550 VALUES (1);
SYS> ALTER TABLE scott.tt550 ENABLE VALIDATE CONSTRAINT tt550_nn
SYS> SELECT rowid, no
SYS> UPDATE scott.tt550
SYS> ALTER TABLE scott.tt550 ENABLE VALIDATE CONSTRAINT tt550_nn
Step 8. not null 이 사용함인 상태에서 일부러 null 값을 입력하여 not null 이 작동함을 확인 SYS> INSERT INTO scott.tt550 VALUES (null); ↑ null 데이터가 입력되지 않음 |
4) 제약조건 조회하기
- 테이블에 제약조건을 설정하면 그 내용이 딕셔너리에 저장이 되어 있음
- 사용하는 딕셔너리는 USER_CONSTRAINTS와 USER_CONS_COLUMNS이며
데이터베이스 전체의 제약조건을 조회하려면 DBA_CONSTRAINTS와 DBA_CONS_COLUMNS를 사용
사용 예 1: emp4 테이블에 설정되어 있는 제약조건 조회하기 SCOTT> SELECT owner, constraint_name, constraint_type, status |
- constraint_type 의 타입 값 중 P: Primary Key , U :Unique , C: CHECK , R:외래키를 의미
사용 예 2: FOREIGN KEY 조회하기 SCOTT> COL child_table FOR a15 SCOTT> SELECT a.table_name "Child_Table", |
5) 제약조건 삭제하기
SCOTT> ALTER TABLE emp4 |
서진수,『오라클 SQL과 PL/SQL』, 생능출판사, 2012, pp.282-299
'Oracle > Oracle_SQL' 카테고리의 다른 글
[10장] VIEW(뷰) (0) | 2014.10.31 |
---|---|
[9장] INDEX(인덱스) (0) | 2014.10.30 |
[7장] DDL 문장과 딕셔너리 (0) | 2014.10.24 |
[6장] DML (0) | 2014.10.23 |
[5장] Sub Query (서브쿼리) (0) | 2014.10.22 |