[Oracle] 26.무결성 제약조건(2)


테이블 레벨에서 제약조건 지정



저번 장에서는 다음과 같이 속성레벨에서 제약조건을 지정해주었습니다.


-- 속성레벨에서 제약조건 지정

CREATE TABLE EMP01(
    empno NUMBER(4) PRIMARY KEY,
    ename VARCHAR2(10) NOT NULL,
    job VARCHAR2(9),
    deptno NUMBER(2) REFERENCES DEPT01(DEPTNO)
);



그러나 다음과 같이 테이블 레벨에서도 제약조건을 지정해줄 수 있습니다.


-- 테이블레벨에서 제약조건 지정

CREATE TABLE emp01 (
    empno    NUMBER(4),
    ename    VARCHAR2(10) NOT NULL,
    job      VARCHAR2(9),
    deptno   NUMBER(2),
    PRIMARY KEY ( empno ),
    UNIQUE ( job ),
    FOREIGN KEY ( deptno ) REFERENCES departments ( department_id )
);



주의할 점은 NOT NULL 제약조건은 속성 레벨에서만 지정할 수 있습니다.

제약 조건 명을 부여할 때는 다음과 같이 합니다.


CREATE TABLE emp01 (
    empno    NUMBER(4),
    ename    VARCHAR2(10)
        CONSTRAINT emp03_ename_nn NOT NULL,
    job      VARCHAR2(9),
    deptno   NUMBER(2),
    CONSTRAINT emp01_empno_pk PRIMARY KEY ( empno ),
    CONSTRAINT emp01_job_uk UNIQUE ( job ),
    CONSTRAINT emp01_deptno_fk FOREIGN KEY ( deptno ) REFERENCES departments ( department_id )
);



복합키를 기본키로 설정



테이블 레벨에서 제약조건을 지정하면 복합키를 기본키로 설정하거나, 여러 속성에 한꺼번에 제약조건을 지정할 수 있습니다!

복합키를 기본키로 설정하는 방법은 다음과 같습니다.


CREATE TABLE emp02 (
    name      VARCHAR2(10),
    address   VARCHAR2(30),
    hphone    VARCHAR2(16),
    CONSTRAINT emp02_combo_pk PRIMARY KEY ( name, phone )
);



제약조건 추가하기



이번에는 이번에는 이미 생성된 테이블에 제약조건을 추가하는 방법에 대해 알아보겠습니다.


--제약조건 미지정

CREATE TABLE emp01 (
    empno    NUMBER(4),
    ename    VARCHAR2(10),
    job      VARCHAR2(9),
    deptno   NUMBER(2)
);



제약조건을 추가할 때는 ALTER 문을 이용합니다~


ALTER TABLE emp01 ADD CONSTRAINT emp01_empno_pk PRIMARY KEY(empno);

ALTER TABLE emp01 ADD CONSTRAINT emp01_deptno_fk FOREIGN KEY(deptno) REFERENCES dept01(deptno);



이 때 주의할 점은 NOT NULL 제약조건은 ADD로 추가불가하므로 MODIFY로 변경해야 합니다.


ALTER TABLE emp01 MODIFY ename CONSTRAINT emp01_ename_nn NOT NULL;



제약조건 제거



제약조건을 제거하려면 DROP 문을 이용합니다.


ALTER TABLE emp01 DROP CONSTRAINT emp01_ename_nn;



제약조건의 비활성화



두 테이블 emp01,dept01이 있다고 가정합시다.


image



현재 emp01 테이블의 deptno 속성은 외래키로써 dept01 테이블의 deptno 속성을 참조하고 있습니다.

이 때 다음과 같은 delete 문은 오류를 발생시킵니다.


DELETE FROM dept01 WHERE deptno=10; -- 연결되어 있는 자식레코드가 있어서 제거 불가(참조하고있는 레코드가 존재)



만약 위의 delete문을 실행하려면 다음과 같이 해야합니다.

  • 참조하고 있는 레코드들을 다 지운다.



  • 제약조건 제거



  • 제약조건 비활성화



제약조건을 비활성화 하려면 다음과 같이 합니다.


ALTER TABLE emp01 DISABLE CONSTRAINT emp01_deptno_fk;



그럼 아까의 delete 문을 실행할 수 있습니다.

다시 활성화를 하려면, 지웠던 컬럼을 다시 넣고 해야합니다.


INSERT INTO dept01 VALUES (10,'개발부',DEFAULT);

ALTER TABLE emp01 ENABLE CONSTRAINT emp01_deptno_fk;



CASCADE



부모 테이블과 자식 테이블 간의 참조 설정이 되어 있을 때 부모 테이블의 제약조건을

비활성화하면 이를 참조하고 있는 자식테이블의 제약조건까지 같이 비활성화 시킬 수 있습니다.

CASCADE 를 이용하면 됩니다.

만약, 이전의 테이블 emp01과 dept01 에서 다음과 같이 dept01 테이블의 기본키 제약조건을 비활성화 시키려고 했을때


ALTER TABLE dept01 DISABLE CONSTRAINT dept01_deptno_pk;



자식테이블 emp01의 외래키 제약조건때문에 오류가 발생합니다.


image




하지만, CASCADE를 추가하면 자식 테이블의 제약조건 까지 비활성화 시켜버립니다.


ALTER TABLE dept01 DISABLE CONSTRAINT dept01_deptno_pk CASCADE; --한번에 부모와 자식 제약조건 비활성화



활성화 할 때도 부모 제약조건 활성화 한 후에 자식 제약조건을 활성화 해야합니다.


ALTER TABLE emp01 ENABLE CONSTRAINT emp01_deptno_fk; -- 활성화 할 때도 부모 제약조건 활성화한후에 가능
ALTER TABLE dept01 ENABLE CONSTRAINT dept01_deptno_pk;



부모테이블의 제약조건 삭제 시 자식 테이블의 제약조건도 삭제되게 할때도 CASCADE를 이용합니다!


ALTER TABLE dept01 DROP CONSTRAINT dept01_deptno_pk CASCADE; --emp01_deptno_fk도 같이 삭제



자식 테이블의 외래키 제약조건에 ON DELETE CASCADE를 추가하면,

외래키가 참조하는 부모 테이블의 기본키가 삭제되었을 때 같이 삭제되도록 할 수 있습니다.


CREATE TABLE emp01 (
    empno    NUMBER(4),
    ename    VARCHAR2(10)
        CONSTRAINT emp03_ename_nn NOT NULL,
    job      VARCHAR2(9),
    deptno   NUMBER(2),
    CONSTRAINT emp01_empno_pk PRIMARY KEY ( empno ),
    CONSTRAINT emp01_deptno_fk FOREIGN KEY ( deptno )
        REFERENCES dept01 ( deptno )
            ON DELETE CASCADE
);




DELETE FROM DEPT01 WHERE DEPTNO='10'; -- 데이터 삭제시 DEPT01의 DEPTNO을 참조하는 EMP01의 데이터도 같이 삭제