Oracle

게시글 보기
작성자 유건데이타 등록일 2015-05-16
제목 DEFERRED CONSTRAINT 와 FOREIGN KEY CONSTRAINTS
Oracle7 까지는 constraint를 일시적으로 diable함으로써 constraint check를
하지 않도록 할 수 있었다. Oracle8에서는 이에 더해서 'Deferred Constraint'
를 이용하여 commit 시점까지 constraint checking을 지연시킬 수 있다.

Deferred Constraint Checking
============================
Oracle에는 다음의 다섯가지의 constraint가 존재한다.
1. Not Null
2. Unique Key
3. Primary Key
4. Foreign Key
5. Check

각 constraint는 특정 column들의 integrity를 보장하는데 사용되며, Oracle7
까지는 각 SQL statement 단위로 check를 하게 된다. 따라서 violation이
발생한 해당 statement만이 rollback되게 된다.
반면에 Oracle8에서 새로 추가된 deferred constraint는 commit시점에 해당
transaction내의 모든 작업에 대한 check를 하며 violation이 발생하면 전체
transaction이 rollback된다.

Constraint 설정
===============
Oracle8에서는 크게 다음과 같이 두가지의 형태로 constraint를 생성할 수 있다.

1. NOT DEFERRABLE
기존의 constraint checking mechanism과 동일하게 작동하며,
ALTER SESSION SET CONSTRAINT=IMMEDIATE ;
SET CONSTRAINT IMMEDIATE ;
등의 명령어를 이용하여 성격을 변경할 수 없다.

2. DEFERRABLE
기존의 checking mechanism과 deferred checking mechanism간에 다음과
같은 명령어를 이용하여 변경이 가능한 constraint이다.
ALTER SESSION SET CONSTRAINT=IMMEDIATE ;
- 해당 session에서 모든 constraint의 성격을 변경한다.
SET CONSTRAINT IMMEDIATE ;
- 특정 constraint의 성격만을 변경한다.

1) INITIALLY IMMEDIATE
constraint를 생성할 때, 각 statement 단위로 constraint checking을
하게 하지만 이후에 위의 명령어등을 이용하여 그 성격을 DEFERRED로
변경할 수 있다.

2) INITIALLY DEFERRED
constraint를 생성할 때, commit시점까지 constraint checking을
delay하도록 하지만 이후에 위의 명령어등을 이용하여 그 성격을
IMMEDIATE로 변경할 수 있다.

Constraint 설정 예
==================
1. NOT DEFERRABLE의 경우
CREATE TABLE not_deferrable
(col1 CHAR(1) CONSTRAINT const1 NOT NULL NOT DEFERRABLE) ;

2. INITIALLY IMMEDIATE의 경우
CREATE TABLE init_immediate
(col1 CHAR(1) CONSTRAINT pk1 PRIMARY KEY DEFERRABLE INITIALLY IMMEDIATE) ;
사용중 deferred로 변경하기 위해서는,
ALTER SESSION SET CONSTRAINT=DEFERRED ; 또는
SET CONSTRAINT pk1 DEFERRED ;

3. INITIALLY DEFERRED의 경우
CREATE TABLE init_deferred
(col1 CHAR(1) CONSTRAINT pk2 PRIMARY KEY
DEFERRABLE INITIALLY DEFERRED) ;
사용중 immediate로 변경하기 위해서는,
ALTER SESSION SET CONSTRAINT=IMMEDIATE ; 또는
SET CONSTRAINT pk2 IMMEDIATE ;

관련 Data Dictionary
====================
_CONSTRAINTS dictionary view의 다음 column등을 이용하여 deferred
constraint 관련 정보를 확인할 수 있다.

DEFERRABLE : NOT DEFERRABLE or DEFERRABLE
DEFERRED : IMMEDIATE or DEFERRED

참고 : ALTER SESSION ... ; 이나 SET CONSTRAINT ... ; 를 이용하여
constraint의 성격을 변경한다고 해서 dictionary의 DEFERRED column의
값이 변경되지는 않는다.

Deferred Constraint를 이용한 Foreign Key관련 작업 예
====================================================
Deferred Constraint를 이용하면, child table의 row를 삭제한 후에 관련
parent row들을 삭제하는 작업, parent key value를 변경하는 작업등을 손쉽게
할 수 있다.

------------------------------Begin Script----------------------------
DROP TABLE EMP;
DROP TABLE DEPT;

CREATE TABLE DEPT (
DEPTNO NUMBER(2) NOT NULL,
DNAME CHAR(14),
LOC CHAR(13),
CONSTRAINT DEPT_PRIMARY_KEY PRIMARY KEY (DEPTNO));

INSERT INTO DEPT VALUES (10,'ACCOUNTING','NEW YORK');
INSERT INTO DEPT VALUES (20,'RESEARCH','DALLAS');
INSERT INTO DEPT VALUES (30,'SALES','CHICAGO');
INSERT INTO DEPT VALUES (40,'OPERATIONS','BOSTON');

CREATE TABLE EMP (
EMPNO NUMBER(4) NOT NULL,
ENAME CHAR(10),
JOB CHAR(9),
MGR NUMBER(4) CONSTRAINT EMP_SELF_KEY REFERENCES EMP (EMPNO),
HIREDATE DATE,
SAL NUMBER(7,2),
COMM NUMBER(7,2),
DEPTNO NUMBER(2) NOT NULL,
CONSTRAINT EMP_FOREIGN_KEY FOREIGN KEY (DEPTNO)
REFERENCES DEPT (DEPTNO) DEFERRABLE INITIALLY DEFERRED,
CONSTRAINT EMP_PRIMARY_KEY PRIMARY KEY (EMPNO));

INSERT INTO EMP VALUES (7839,'KING','PRESIDENT',NULL,'17-NOV-81',5000,NULL,10);
INSERT INTO EMP VALUES (7698,'BLAKE','MANAGER',7839,'1-MAY-81',2850,NULL,30);
INSERT INTO EMP VALUES (7782,'CLARK','MANAGER',7839,'9-JUN-81',2450,NULL,10);
INSERT INTO EMP VALUES (7566,'JONES','MANAGER',7839,'2-APR-81',2975,NULL,20);
INSERT INTO EMP VALUES (7654,'MARTIN','SALESMAN',7698,'28-SEP-81',1250,1400,30);
INSERT INTO EMP VALUES (7499,'ALLEN','SALESMAN',7698,'20-FEB-81',1600,300,30);
INSERT INTO EMP VALUES
(7844,'TURNER','SALESMAN',7698,'8-SEP-81',1500,0,30);
INSERT INTO EMP VALUES
(7900,'JAMES','CLERK',7698,'3-DEC-81',950,NULL,30);
INSERT INTO EMP VALUES (7521,'WARD','SALESMAN',7698,'22-FEB-81',1250,500,30);
INSERT INTO EMP VALUES
(7902,'FORD','ANALYST',7566,'3-DEC-81',3000,NULL,20);
INSERT INTO EMP VALUES
(7369,'SMITH','CLERK',7902,'17-DEC-80',800,NULL,20);
INSERT INTO EMP VALUES (7788,'SCOTT','ANALYST',7566,'09-DEC-82',3000,NULL,20);
INSERT INTO EMP VALUES
(7876,'ADAMS','CLERK',7788,'12-JAN-83',1100,NULL,20);
INSERT INTO EMP VALUES (7934,'MILLER','CLERK',7782,'23-JAN-82',1300,NULL,10);
commit;
---------------------------------End Script---------------------------

Deferred Constraint가 아니라면, 다음의 작업은 error를 유발할 것이다.

SQL> delete dept where deptno=20;

delete dept where deptno=20
*
ERROR at line 1:
ORA-02292: integrity constraint (WOOKPARK.EMP_FOREIGN_KEY) violated
- child record found

이 시점에서 위의 statement는 rollback 되며, 20번 부서는 삭제되지 않는다.

Deferred Constraint를 이용한다면 다음과 같이 commit시점까지는 error를
유발하지 않는다.

SQL> delete dept where deptno = 20 ;

1 row deleted.

SQL> commit ;
commit
*
ERROR at line 1:
ORA-02091: transaction rolled back
ORA-02292: integrity constraint (WOOKPARK.EMP_FOREIGN_KEY) violated
- child record found

만약 commit하기전에 부서번호 20번에 속한 사원을 삭제한다면 commit시에
error가 발생하지 않는다.

SQL> delete dept where deptno=20;

1 row deleted.

SQL> delete emp where deptno=20;

5 rows deleted.

SQL> commit;

Commit complete.


Deferred Donstraint는 다음과 같이 parent table의 primary key value를
변경하는 작업에도 유용하게 사용될 수 있다.

SQL> update dept set deptno=25 where deptno=20;

1 row updated.

SQL> update emp set deptno=25 where deptno=20;

5 rows updated.

SQL> commit;
Comment
등록된 코멘트가 없습니다.