DELETE
를 사용한다delete from tb_name
WHERE
절 없이 DELETE
를 사용하면 지정된 테이블에서 모든 행을 삭제한다TRUNCATE
를 적용하면 WHERE
절을 사용하지 않아도 되기에 더 빠르다TRUNCATE
를 취소할 수 없다TRUNCATE
와 DELETE
간 성능 및 롤백 가능 여부에 차이가 있다DELETE
명령에 WHERE
절을 사용하여 행을 제한한다delete from emp where deptno = 10
delete from emp where empno = 7782
제목만 보면 이게 뭔 말인가 싶다.
예를 들어,
일부 사원이, 현재 존재하지 않는 부서에 할당되었을 때, 해당 사원을 삭제하고자 한다.
WHERE
절의 서브쿼리에 EXISTS
를 사용한다또는 NOT IN
을 사용할 수도 있다.
/* 전후 비교를 위해 */
select * from emp;
>>
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
7839 KING PRESIDENT - 17-NOV-81 5000 - 10
7698 BLAKE MANAGER 7839 01-MAY-81 2850 - 30
7782 CLARK MANAGER 7839 09-JUN-81 2450 - 10
7566 JONES MANAGER 7839 02-APR-81 2975 - 20
7788 SCOTT ANALYST 7566 19-APR-87 3000 - 20
7902 FORD ANALYST 7566 03-DEC-81 3000 - 20
7369 SMITH CLERK 7902 17-DEC-80 800 - 20
7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30
7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30
7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30
7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30
7876 ADAMS CLERK 7788 23-MAY-87 1100 - 20
7900 JAMES CLERK 7698 03-DEC-81 950 - 30
7934 MILLER CLERK 7782 23-JAN-82 1300 - 10
14 rows selected.
delete from emp
where not exists(
select * from dept
where dept.deptno = emp.deptno
);
>>
0 row(s) deleted.
'EMP' 테이블의 모든 부서값이 'DEPT' 테이블에 존재하므로 삭제되지 않은 것을 볼 수 있다.
임의의 레코드를 하나 집어 넣어서 확인해야겠다.
insert into emp values
(
9999, 'TESTER', 'TESTER', 9999, to_date('19-11-2020', 'dd-mm-yyyy'),
9999, 9999, 50
)
>>
ORA-00001: unique constraint (SQL_YIDSMRNAPUVJERHCFFLWNSQXS.PK_EMP) violated ORA-06512: at "SYS.DBMS_SQL", line 1721
오류가 난다. DEPTNO
가 KEY로 설정되어 있기 때문인가 해서 KEY를 DROP했다.
ALTER TABLE emp DROP CONSTRAINT fk_deptno;
>>
Table altered.
select * from emp;
>>
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
7839 KING PRESIDENT - 17-NOV-81 5000 - 10
7698 BLAKE MANAGER 7839 01-MAY-81 2850 - 30
7782 CLARK MANAGER 7839 09-JUN-81 2450 - 10
7566 JONES MANAGER 7839 02-APR-81 2975 - 20
7788 SCOTT ANALYST 7566 19-APR-87 3000 - 20
7902 FORD ANALYST 7566 03-DEC-81 3000 - 20
7369 SMITH CLERK 7902 17-DEC-80 800 - 20
7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30
7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30
7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30
7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30
7876 ADAMS CLERK 7788 23-MAY-87 1100 - 20
7900 JAMES CLERK 7698 03-DEC-81 950 - 30
7934 MILLER CLERK 7782 23-JAN-82 1300 - 10
9999 TESTER TESTER 9999 19-NOV-20 9999 9999 50
15 rows selected.
마지막 행에 값이 정상적으로 잘 들어갔다.
'EMP' 테이블의 'DEPTNO'칼럼에, 'DEPT' 테이블의 'DEPTNO'를 참조하는 방식의 외부키를 걸어뒀었다.
'DEPT' 테이블에서 'DEPTNO'는 고유하므로, 'DEPT' 테이블에는 존재하지 않는 'DEPTNO' 값을 넣으려다보니 오류가 났던 것이다.
이 상태에서 부서가 존재하지 않는 사원의 삭제를 다시 시도해보겠다.
/* 그 전에, 혹시나해서 'EMP' 테이블의 'DEPTNO'에 FK 제약조건을 걸어보려 했다 */
alter table emp add constraint fk_deptno foreign key (deptno) references dept (deptno)
>>
ORA-02298: cannot validate (SQL_QXNARBILYUMUWIVEGKISYZYFE.FK_DEPTNO) - parent keys not found
/* 없는 값이 있는 상태에서 FK를 넣으려다 보니 역시나 오류가 발생한다 */
delete from emp
where not exists(
select * from dept
where dept.deptno = emp.deptno
);
>>
1 row(s) deleted.
select * from emp;
>>
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
7839 KING PRESIDENT - 17-NOV-81 5000 - 10
7698 BLAKE MANAGER 7839 01-MAY-81 2850 - 30
7782 CLARK MANAGER 7839 09-JUN-81 2450 - 10
7566 JONES MANAGER 7839 02-APR-81 2975 - 20
7788 SCOTT ANALYST 7566 19-APR-87 3000 - 20
7902 FORD ANALYST 7566 03-DEC-81 3000 - 20
7369 SMITH CLERK 7902 17-DEC-80 800 - 20
7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30
7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30
7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30
7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30
7876 ADAMS CLERK 7788 23-MAY-87 1100 - 20
7900 JAMES CLERK 7698 03-DEC-81 950 - 30
7934 MILLER CLERK 7782 23-JAN-82 1300 - 10
14 rows selected.
TESTER가 사라진 것을 볼 수 있다.
NOT IN
을 사용하는 쿼리는 다음과 같다.
delete from emp
where deptno not in (select deptno from dept)
삭제는 , 실제로는 '선택'에 관한 문제다.
삭제하려는 레코드를 올바르게 설명하기 위해 WHERE
절 조건을 정교하게 작성하는 것이다.
NOT EXISTS
해법
: 상관 서브쿼리를 사용하여 DEPTNO가 일치하는 레코드가 있는지 검증하고, 그 결과에 따라 삭제 여부도 결정되는 방식이다.
IN
해법
: 서브쿼리를 이용하여 부서 번호 목록을 검색한 후, 이 결과셋과 'EMP' 테이블의 부서 번호 목록을 비교했다. 목록에 없는 DEPTNO를 사용하는 EMP 레코드를 발견했을 때 삭제하는 방식을 사용했다.
다소 난도가 낮은 쿼리였지만, 고유한 값이 있고 FK로 연결되어 있을 때 INSERT
내지 UPDATE
가 어떻게 작동하는지 알 수 있었다.
NULL
허용 여부)